• Re: official library of tiny functions lacking in c

    From fir@profesor.fir@gmail.com to comp.lang.c on Sun Sep 27 20:04:20 2026
    From Newsgroup: comp.lang.c

    fir pisze:
    you know there are a lacking tiny functions in c-lib
    (by c-lib i mean those standard c includes all know)

    AND if people use many maybe there is a need to standarize it
    byslef? if you need some could be ggood candidates for standarisation
    maybe write it here (i mean whole body of such function)

    we could and should discuss them


    maybe something liek this?


    int mini(int a,int b) { return a<b?a:b; }
    int maxi(int a,int b) { return a>b?a:b; }
    float minf(float a,float b) { return a<b?a:b; }
    float maxf(float a,float b) { return a>b?a:b; }
    int absi(int x) { return x<0?-x:x; }
    float absf(float x) { return x<0?-x:x; }
    float signf(float x) { return x>0?1:x<0?-1:0; }
    int signi(int x) { return x>0?1:x<0?-1:0; }

    //above controversial?

    int clampi(int x,int a,int b) { return x<a?a:x>b?b:x; }
    float clampf(float x,float a,float b) { return x<a?a:x>b?b:x; }
    int betweeni(int x,int a,int b) { return x>=a && x<=b; }

    float lerp(float a,float b,float t) { return a+(b-a)*t; }
    float inv_lerp(float a,float b,float x) { return (x-a)/(b-a); }
    float remap(float x,float a,float b,float c,float d) { return c+(x-a)*(d-c)/(b-a); }
    float rad(float x) { return x*PI/180.0f; }
    float deg(float x) { return x*180.0f/PI; }

    //thise above i dont quite use

    float dist2_square(float x1,float y1,float x2,float y2) { float x=x2-x1,y=y2-y1; return x*x+y*y; }
    float dist2(float x1,float y1,float x2,float y2) { return sqrtf(dist2(x1,y1,x2,y2));}
    float len2_square(float x,float y) { return x*x+y*y; }
    float len2(float x,float y) { return sqrtf(x*x+y*y);}
    float dot2(float ax,float ay,float bx,float by){ return ax*bx+ay*by;}
    float cross2(float ax,float ay,float bx,float by){ return ax*by-ay*bx;}
    void norm2(float *x,float *y) { float d=sqrtf(*x**x+*y**y); if(d>0)
    { *x/=d; *y/=d; }}
    float dist2_to_line(float px,float py,float ax,float ay,float bx,float
    by){ return fabsf(cross2(bx-ax,by-ay,px-ax,py-ay)) /sqrtf(dist2_square(ax,ay,bx,by));}

    // hare names may be controversial

    the fact is imo though people should generallu decide and use one set of
    such names imo

    there is also more functions to put here
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Sun Sep 27 21:38:39 2026
    From Newsgroup: comp.lang.c

    On 27/09/2026 19:04, fir wrote:
    fir pisze:
    you know there are a lacking tiny functions in c-lib
    (by c-lib i mean those standard c includes all know)

    AND if people use many maybe there is a need to standarize it
    byslef? if you need some could be ggood candidates for standarisation
    maybe write it here (i mean whole body of such function)

    we could and should discuss them


    maybe something liek this?


    int mini(int a,int b) { return a<b?a:b; }
    int maxi(int a,int b) { return a>b?a:b; }
    float minf(float a,float b) { return a<b?a:b; }
    float maxf(float a,float b) { return a>b?a:b; }
    int absi(int x) { return x<0?-x:x; }
    float absf(float x) { return x<0?-x:x; }
    float signf(float x) { return x>0?1:x<0?-1:0; }
    int signi(int x) { return x>0?1:x<0?-1:0; }

    //above controversial?

    int clampi(int x,int a,int b) { return x<a?a:x>b?b:x; }
    float clampf(float x,float a,float b) { return x<a?a:x>b?b:x; }
    int betweeni(int x,int a,int b) {-a return x>=a && x<=b; }


    My systems language has these as built-ins. That means they are
    overloaded for all numeric types.

    Here, a, b, c are signed or unsigned 64-bit ints, and x,y,z can be 32-
    or 64-bit floats:

    min(a, b)
    min(x, y)
    max(x, y)
    max(x, y)
    abs(a)
    abs(x)
    sign(a)
    sign(x)
    clamp(a, b, c)
    clamp(x, y, z)
    a in b..c # or:
    b <= a <= c
    x <= y <= z

    I wouldn't have a problem with these being part of standard C. But since
    they will be functions (they will never be added to the core), you will
    need versions for:

    i32 u32 i64 u64 f32 f64

    You might get away having only 64-bit versions, but on 32-targets that
    would be inefficient.

    Note that abs, labs, llabs, fabs, fabsf already exist in the standard
    library. Notice that 'abs' has 3 integer versions, so it is possible it
    can get even uglier than I said; you might need versions for:

    int, long, long long, i32 i64
    unsigned int, unsigned long, unsigned long long, u32 u64

    to cover both 'classic' int types and ones from stdint.h.

    (abs() will only need signed; but anything involving comparisons needs
    both.)



    float lerp(float a,float b,float t) { return a+(b-a)*t; }
    float inv_lerp(float a,float b,float x) { return (x-a)/(b-a); }
    float remap(float x,float a,float b,float c,float d) { return c+(x- a)*(d-c)/(b-a); }

    I've never heard of these.

    float rad(float x) { return x*PI/180.0f; }
    float deg(float x) { return x*180.0f/PI; }

    //thise above i dont quite use

    float dist2_square(float x1,float y1,float x2,float y2) {-a-a float x=x2- x1,y=y2-y1;-a-a-a-a return x*x+y*y; }
    float dist2(float x1,float y1,float x2,float y2) {-a-a-a return sqrtf(dist2(x1,y1,x2,y2));}
    float len2_square(float x,float y) {-a-a-a return x*x+y*y; }
    float len2(float x,float y) {-a return sqrtf(x*x+y*y);}
    float dot2(float ax,float ay,float bx,float by){-a-a return ax*bx+ay*by;} float cross2(float ax,float ay,float bx,float by){-a-a-a return ax*by-ay*bx;} void-a norm2(float *x,float *y) {-a float d=sqrtf(*x**x+*y**y);-a-a if(d>0) { *x/=d;-a *y/=d; }}
    float dist2_to_line(float px,float py,float ax,float ay,float bx,float by){-a-a-a return fabsf(cross2(bx-ax,by-ay,px-ax,py-ay)) / sqrtf(dist2_square(ax,ay,bx,by));}

    This will be application-specific and don't really belong in a language
    like C. They can be in a third-party library.

    (I used to have many of these in my first scripting language, but that
    was part of my 3D graphics apps. It was a sort of DSL. My current
    scripting language doesn't have them.)

    But if such a library is created, it needs to have a lot more. Like
    supporting 3D for a start. Beyond that it would again depend on
    application.)


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@profesor.fir@gmail.com to comp.lang.c on Sun Sep 27 23:16:50 2026
    From Newsgroup: comp.lang.c

    bart pisze:
    On 27/09/2026 19:04, fir wrote:
    fir pisze:
    you know there are a lacking tiny functions in c-lib
    (by c-lib i mean those standard c includes all know)

    AND if people use many maybe there is a need to standarize it
    byslef? if you need some could be ggood candidates for standarisation
    maybe write it here (i mean whole body of such function)

    we could and should discuss them


    maybe something liek this?


    int mini(int a,int b) { return a<b?a:b; }
    int maxi(int a,int b) { return a>b?a:b; }
    float minf(float a,float b) { return a<b?a:b; }
    float maxf(float a,float b) { return a>b?a:b; }
    int absi(int x) { return x<0?-x:x; }
    float absf(float x) { return x<0?-x:x; }
    float signf(float x) { return x>0?1:x<0?-1:0; }
    int signi(int x) { return x>0?1:x<0?-1:0; }

    //above controversial?

    int clampi(int x,int a,int b) { return x<a?a:x>b?b:x; }
    float clampf(float x,float a,float b) { return x<a?a:x>b?b:x; }
    int betweeni(int x,int a,int b) {-a return x>=a && x<=b; }


    My systems language has these as built-ins. That means they are
    overloaded for all numeric types.

    Here, a, b, c are signed or unsigned 64-bit ints, and x,y,z can be 32-
    or 64-bit floats:

    -a-a-a min(a, b)
    -a-a-a min(x, y)
    -a-a-a max(x, y)
    -a-a-a max(x, y)
    -a-a-a abs(a)
    -a-a-a abs(x)
    -a-a-a sign(a)
    -a-a-a sign(x)
    -a-a-a clamp(a, b, c)
    -a-a-a clamp(x, y, z)
    -a-a-a a in b..c-a-a-a-a-a-a-a-a # or:
    -a-a-a b <= a <= c
    -a-a-a x <= y <= z

    I wouldn't have a problem with these being part of standard C. But since they will be functions (they will never be added to the core), you will
    need versions for:

    -a-a i32 u32 i64 u64 f32 f64

    You might get away having only 64-bit versions, but on 32-targets that
    would be inefficient.

    Note that abs, labs, llabs, fabs, fabsf already exist in the standard library. Notice that 'abs' has 3 integer versions, so it is possible it
    can get even uglier than I said; you might need versions for:

    -a-a int, long, long long, i32 i64
    -a-a unsigned int, unsigned long, unsigned long long, u32 u64

    to cover both 'classic' int types and ones from stdint.h.

    (abs() will only need signed; but anything involving comparisons needs both.)



    float lerp(float a,float b,float t) { return a+(b-a)*t; }
    float inv_lerp(float a,float b,float x) { return (x-a)/(b-a); }
    float remap(float x,float a,float b,float c,float d) { return c+(x-
    a)*(d-c)/(b-a); }

    I've never heard of these.

    float rad(float x) { return x*PI/180.0f; }
    float deg(float x) { return x*180.0f/PI; }

    //thise above i dont quite use

    float dist2_square(float x1,float y1,float x2,float y2) {-a-a float
    x=x2- x1,y=y2-y1;-a-a-a-a return x*x+y*y; }
    float dist2(float x1,float y1,float x2,float y2) {-a-a-a return
    sqrtf(dist2(x1,y1,x2,y2));}
    float len2_square(float x,float y) {-a-a-a return x*x+y*y; }
    float len2(float x,float y) {-a return sqrtf(x*x+y*y);}
    float dot2(float ax,float ay,float bx,float by){-a-a return ax*bx+ay*by;}
    float cross2(float ax,float ay,float bx,float by){-a-a-a return
    ax*by-ay*bx;}
    void-a norm2(float *x,float *y) {-a float d=sqrtf(*x**x+*y**y);
    if(d>0) { *x/=d;-a *y/=d; }}
    float dist2_to_line(float px,float py,float ax,float ay,float bx,float
    by){-a-a-a return fabsf(cross2(bx-ax,by-ay,px-ax,py-ay)) /
    sqrtf(dist2_square(ax,ay,bx,by));}

    This will be application-specific and don't really belong in a language
    like C. They can be in a third-party library.

    (I used to have many of these in my first scripting language, but that
    was part of my 3D graphics apps. It was a sort of DSL. My current
    scripting language doesn't have them.)

    But if such a library is created, it needs to have a lot more. Like supporting 3D for a start. Beyond that it would again depend on application.)



    i not quite understood why most of it cant be added (?)

    literally i forgot there is fabs and fmin fmax - it is all mess that
    some are some not.. imo it should be standarised just to not various
    names be used for same thing of various thing for same name

    (lask of this standarisatio is also another c annoyance imo)

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From tTh@tth@none.invalid to comp.lang.c on Mon Sep 28 00:02:38 2026
    From Newsgroup: comp.lang.c

    On 9/27/26 10:20, fir wrote:

    AND if people use many maybe there is a need to standarize it
    byslef? if you need some could be ggood candidates for standarisation
    maybe write it here (i mean whole body of such function)

    we could and should discuss them

    double dtime(void)
    {
    struct timeval t;
    double d;
    (void)gettimeofday(&t, NULL);
    d = (double)t.tv_sec + (double)t.tv_usec / 1e6;
    return d;
    }
    --
    ** **
    * tTh des Bourtoulots *
    * http://maison.tth.netlib.re/ *
    ** **
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Mon Sep 28 00:53:11 2026
    From Newsgroup: comp.lang.c

    On 27/09/2026 22:16, fir wrote:
    bart pisze:
    On 27/09/2026 19:04, fir wrote:
    fir pisze:
    you know there are a lacking tiny functions in c-lib
    (by c-lib i mean those standard c includes all know)

    AND if people use many maybe there is a need to standarize it
    byslef? if you need some could be ggood candidates for
    standarisation maybe write it here (i mean whole body of such function) >>>>
    we could and should discuss them


    maybe something liek this?


    int mini(int a,int b) { return a<b?a:b; }
    int maxi(int a,int b) { return a>b?a:b; }
    float minf(float a,float b) { return a<b?a:b; }
    float maxf(float a,float b) { return a>b?a:b; }
    int absi(int x) { return x<0?-x:x; }
    float absf(float x) { return x<0?-x:x; }
    float signf(float x) { return x>0?1:x<0?-1:0; }
    int signi(int x) { return x>0?1:x<0?-1:0; }

    //above controversial?

    int clampi(int x,int a,int b) { return x<a?a:x>b?b:x; }
    float clampf(float x,float a,float b) { return x<a?a:x>b?b:x; }
    int betweeni(int x,int a,int b) {-a return x>=a && x<=b; }


    My systems language has these as built-ins. That means they are
    overloaded for all numeric types.

    Here, a, b, c are signed or unsigned 64-bit ints, and x,y,z can be 32-
    or 64-bit floats:

    -a-a-a-a min(a, b)
    -a-a-a-a min(x, y)
    -a-a-a-a max(x, y)
    -a-a-a-a max(x, y)
    -a-a-a-a abs(a)
    -a-a-a-a abs(x)
    -a-a-a-a sign(a)
    -a-a-a-a sign(x)
    -a-a-a-a clamp(a, b, c)
    -a-a-a-a clamp(x, y, z)
    -a-a-a-a a in b..c-a-a-a-a-a-a-a-a # or:
    -a-a-a-a b <= a <= c
    -a-a-a-a x <= y <= z

    I wouldn't have a problem with these being part of standard C. But
    since they will be functions (they will never be added to the core),
    you will need versions for:

    -a-a-a i32 u32 i64 u64 f32 f64

    You might get away having only 64-bit versions, but on 32-targets that
    would be inefficient.

    Note that abs, labs, llabs, fabs, fabsf already exist in the standard
    library. Notice that 'abs' has 3 integer versions, so it is possible
    it can get even uglier than I said; you might need versions for:

    -a-a-a int, long, long long, i32 i64
    -a-a-a unsigned int, unsigned long, unsigned long long, u32 u64

    to cover both 'classic' int types and ones from stdint.h.

    (abs() will only need signed; but anything involving comparisons needs
    both.)



    float lerp(float a,float b,float t) { return a+(b-a)*t; }
    float inv_lerp(float a,float b,float x) { return (x-a)/(b-a); }
    float remap(float x,float a,float b,float c,float d) { return c+(x-
    a)*(d-c)/(b-a); }

    I've never heard of these.

    float rad(float x) { return x*PI/180.0f; }
    float deg(float x) { return x*180.0f/PI; }

    //thise above i dont quite use

    float dist2_square(float x1,float y1,float x2,float y2) {-a-a float
    x=x2- x1,y=y2-y1;-a-a-a-a return x*x+y*y; }
    float dist2(float x1,float y1,float x2,float y2) {-a-a-a return
    sqrtf(dist2(x1,y1,x2,y2));}
    float len2_square(float x,float y) {-a-a-a return x*x+y*y; }
    float len2(float x,float y) {-a return sqrtf(x*x+y*y);}
    float dot2(float ax,float ay,float bx,float by){-a-a return ax*bx+ay*by;} >>> float cross2(float ax,float ay,float bx,float by){-a-a-a return ax*by-
    ay*bx;}
    void-a norm2(float *x,float *y) {-a float d=sqrtf(*x**x+*y**y); if(d>0) >>> { *x/=d;-a *y/=d; }}
    float dist2_to_line(float px,float py,float ax,float ay,float
    bx,float by){-a-a-a return fabsf(cross2(bx-ax,by-ay,px-ax,py-ay)) /
    sqrtf(dist2_square(ax,ay,bx,by));}

    This will be application-specific and don't really belong in a
    language like C. They can be in a third-party library.

    (I used to have many of these in my first scripting language, but that
    was part of my 3D graphics apps. It was a sort of DSL. My current
    scripting language doesn't have them.)

    But if such a library is created, it needs to have a lot more. Like
    supporting 3D for a start. Beyond that it would again depend on
    application.)



    i not quite understood why most of it cant be added (?)

    Because it is application-specific as I said.

    Ones like MIN(x, y) can be considered fundamental, but not the length of
    a 2D vector which takes discrete X, Y float arguments.

    It is just too specific, and the requirements in real applications will
    be too diverse.

    And also, where do you stop; why not a string library and a million
    other things?

    I'm sure there are plenty of such libraries about. They don't need to be
    core language features at this level.


    literally i forgot there is fabs and fmin fmax - it is all mess that
    some are some not.. imo it should be standarised just to not various
    names be used for same thing of various thing for same name

    I wasn't aware of fmin etc. But they can't use the same name as there
    needs to be one function for each type.

    Unless fminl/fmaxl, which take 'long double', also deal with float and
    double, but it can mean expensive conversions.

    (lask of this standarisatio is also another c annoyance imo)


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@profesor.fir@gmail.com to comp.lang.c on Mon Sep 28 04:31:35 2026
    From Newsgroup: comp.lang.c

    bart pisze:
    On 27/09/2026 22:16, fir wrote:
    bart pisze:
    On 27/09/2026 19:04, fir wrote:
    fir pisze:
    you know there are a lacking tiny functions in c-lib
    (by c-lib i mean those standard c includes all know)

    AND if people use many maybe there is a need to standarize it
    byslef? if you need some could be ggood candidates for
    standarisation maybe write it here (i mean whole body of such
    function)

    we could and should discuss them


    maybe something liek this?


    int mini(int a,int b) { return a<b?a:b; }
    int maxi(int a,int b) { return a>b?a:b; }
    float minf(float a,float b) { return a<b?a:b; }
    float maxf(float a,float b) { return a>b?a:b; }
    int absi(int x) { return x<0?-x:x; }
    float absf(float x) { return x<0?-x:x; }
    float signf(float x) { return x>0?1:x<0?-1:0; }
    int signi(int x) { return x>0?1:x<0?-1:0; }

    //above controversial?

    int clampi(int x,int a,int b) { return x<a?a:x>b?b:x; }
    float clampf(float x,float a,float b) { return x<a?a:x>b?b:x; }
    int betweeni(int x,int a,int b) {-a return x>=a && x<=b; }


    My systems language has these as built-ins. That means they are
    overloaded for all numeric types.

    Here, a, b, c are signed or unsigned 64-bit ints, and x,y,z can be
    32- or 64-bit floats:

    -a-a-a-a min(a, b)
    -a-a-a-a min(x, y)
    -a-a-a-a max(x, y)
    -a-a-a-a max(x, y)
    -a-a-a-a abs(a)
    -a-a-a-a abs(x)
    -a-a-a-a sign(a)
    -a-a-a-a sign(x)
    -a-a-a-a clamp(a, b, c)
    -a-a-a-a clamp(x, y, z)
    -a-a-a-a a in b..c-a-a-a-a-a-a-a-a # or:
    -a-a-a-a b <= a <= c
    -a-a-a-a x <= y <= z

    I wouldn't have a problem with these being part of standard C. But
    since they will be functions (they will never be added to the core),
    you will need versions for:

    -a-a-a i32 u32 i64 u64 f32 f64

    You might get away having only 64-bit versions, but on 32-targets
    that would be inefficient.

    Note that abs, labs, llabs, fabs, fabsf already exist in the standard
    library. Notice that 'abs' has 3 integer versions, so it is possible
    it can get even uglier than I said; you might need versions for:

    -a-a-a int, long, long long, i32 i64
    -a-a-a unsigned int, unsigned long, unsigned long long, u32 u64

    to cover both 'classic' int types and ones from stdint.h.

    (abs() will only need signed; but anything involving comparisons
    needs both.)



    float lerp(float a,float b,float t) { return a+(b-a)*t; }
    float inv_lerp(float a,float b,float x) { return (x-a)/(b-a); }
    float remap(float x,float a,float b,float c,float d) { return c+(x-
    a)*(d-c)/(b-a); }

    I've never heard of these.

    float rad(float x) { return x*PI/180.0f; }
    float deg(float x) { return x*180.0f/PI; }

    //thise above i dont quite use

    float dist2_square(float x1,float y1,float x2,float y2) {-a-a float
    x=x2- x1,y=y2-y1;-a-a-a-a return x*x+y*y; }
    float dist2(float x1,float y1,float x2,float y2) {-a-a-a return
    sqrtf(dist2(x1,y1,x2,y2));}
    float len2_square(float x,float y) {-a-a-a return x*x+y*y; }
    float len2(float x,float y) {-a return sqrtf(x*x+y*y);}
    float dot2(float ax,float ay,float bx,float by){-a-a return ax*bx+ay*by;} >>>> float cross2(float ax,float ay,float bx,float by){-a-a-a return ax*by- >>>> ay*bx;}
    void-a norm2(float *x,float *y) {-a float d=sqrtf(*x**x+*y**y);
    if(d>0) { *x/=d;-a *y/=d; }}
    float dist2_to_line(float px,float py,float ax,float ay,float
    bx,float by){-a-a-a return fabsf(cross2(bx-ax,by-ay,px-ax,py-ay)) /
    sqrtf(dist2_square(ax,ay,bx,by));}

    This will be application-specific and don't really belong in a
    language like C. They can be in a third-party library.

    (I used to have many of these in my first scripting language, but
    that was part of my 3D graphics apps. It was a sort of DSL. My
    current scripting language doesn't have them.)

    But if such a library is created, it needs to have a lot more. Like
    supporting 3D for a start. Beyond that it would again depend on
    application.)



    i not quite understood why most of it cant be added (?)

    Because it is application-specific as I said.

    Ones like MIN(x, y) can be considered fundamental, but not the length of
    a 2D vector which takes discrete X, Y float arguments.

    It is just too specific, and the requirements in real applications will
    be too diverse.



    how specyfic? i dont understand this

    where to stop? imo the ones that are commo usage should be standarised
    it doesnt even mean they need to be implemented in library but there
    should be common naming (and the same work at least in the same ciricumstances)



    And also, where do you stop; why not a string library and a million
    other things?


    string library is for ery rare use imo, except printing texts and numbers...most problems are with that simple math related functions..
    alos maybe color realated and simple 2d graphics could be standarised


    I'm sure there are plenty of such libraries about. They don't need to be core language features at this level.


    literally i forgot there is fabs and fmin fmax - it is all mess that
    some are some not.. imo it should be standarised just to not various
    names be used for same thing of various thing for same name

    I wasn't aware of fmin etc. But they can't use the same name as there
    needs to be one function for each type.

    Unless fminl/fmaxl, which take 'long double', also deal with float and double, but it can mean expensive conversions.

    (lask of this standarisatio is also another c annoyance imo)



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Mon Sep 28 06:45:43 2026
    From Newsgroup: comp.lang.c

    On Sun, 27 Sep 2026 20:04:20 +0200, fir wrote:

    float len2(float x,float y) { return sqrtf(x*x+y*y);}

    Interesting:

    /*
    Comparison of the na|>ve calculation of a triangle
    hypotenuse with the standard-library hypot(3) function.
    */

    #include <math.h>
    #include <values.h>
    #include <stdio.h>

    static float len2(float x,float y) { return sqrtf(x*x+y*y);}

    static void compare_for
    (
    float x
    )
    {
    fprintf
    (
    stdout,
    "for %.7e: len2 = %.7e, hypot = %.7e\n",
    x, len2(x, x), hypotf(x, x)
    );
    } /*compare_for*/

    int main(void)
    {
    compare_for(FLT_MAX / 2.0f);
    compare_for(2.0 / FLT_MAX);
    return
    0;
    } /*main*/

    Output:

    ldo@theon:c_try> !./
    ./naive_hypot
    for 1.7014117e+38: len2 = inf, hypot = 2.4061594e+38
    for 5.8774718e-39: len2 = 0.0000000e+00, hypot = 8.3120008e-39
    ldo@theon:c_try>

    How is it the standard library function is able to produce a
    reasonable-looking result where your function breaks down?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Mon Sep 28 10:25:02 2026
    From Newsgroup: comp.lang.c

    On 28/09/2026 01:53, bart wrote:

    Ones like MIN(x, y) can be considered fundamental, but not the length of
    a 2D vector which takes discrete X, Y float arguments.


    The C standard library has a several floating point "minimum" and
    "maximum" functions, with different treatment of signed zeros and NaNs.
    In floating point, "a < b ? a : b" is often not sufficient, so these
    functions are needed for users that care about the precise details.

    For integers, "a < b ? a : b" works fine. There is no "min" in the C
    standard library - I suppose the combination of it being easy to write
    in user code, and the common usage of "min" as an identifier meant that
    it could never be added to the C standard library without a somewhat artificial name like "iminimum". Maybe one day C will get namespaces
    (there are proposals in the works) and then it will be fine to add
    stdc::min.

    It also has a "hypot" function that returns, approximately, sqrt(x*x +
    y*y). But again, the actual implementation is not as simple so that it correctly handles rounding, avoids unnecessary overflow or underflow,
    and can conform to IEEE standards and/or take advantage of hardware acceleration.

    It is just too specific, and the requirements in real applications will
    be too diverse.

    And also, where do you stop; why not a string library and a million
    other things?


    C has a string library. It's not very high level, compared to the
    support found in many other languages.

    I'm sure there are plenty of such libraries about. They don't need to be core language features at this level.


    Agreed. Things like "min", "abs", trig functions, etc., should normally
    not be core language features in any language unless the language is
    dedicated to numerical calculations. Lots can be part of a standard
    library, however. There's no rule where the line should be drawn
    between standard libraries and additional libraries - that depends on
    the language. Since we are in c.l.c., the C standards show where the
    line is drawn in C.


    literally i forgot there is fabs and fmin fmax - it is all mess that
    some are some not.. imo it should be standarised just to not various
    names be used for same thing of various thing for same name

    I wasn't aware of fmin etc. But they can't use the same name as there
    needs to be one function for each type.

    C has had type-generic maths macros since C99 - if you use #include
    <tgmath.h> and write "fabs(x)", then the appropriate real or complex
    floating point fabs, fabsf, fabsl, cabs, cabsf, cabsl function will be
    called.

    Since C11, you can write such macros yourself. New functions added to
    the C standard library, such as the <stdbit.h> functions in C23, come in
    both fixed-type function and type-generic macro form.


    Unless fminl/fmaxl, which take 'long double', also deal with float and double, but it can mean expensive conversions.

    Many of the functions Fir wanted are already in the C standard library.
    Many of the features you wanted are already in the language and library.
    You would both benefit from looking at the standards or a good
    reference website before bemoaning missing features and functions.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@profesor.fir@gmail.com to comp.lang.c on Mon Sep 28 12:42:31 2026
    From Newsgroup: comp.lang.c

    Lawrence DrCOOliveiro pisze:
    On Sun, 27 Sep 2026 20:04:20 +0200, fir wrote:

    float len2(float x,float y) { return sqrtf(x*x+y*y);}

    Interesting:

    /*
    Comparison of the na|>ve calculation of a triangle
    hypotenuse with the standard-library hypot(3) function.
    */

    #include <math.h>
    #include <values.h>
    #include <stdio.h>

    static float len2(float x,float y) { return sqrtf(x*x+y*y);}

    static void compare_for
    (
    float x
    )
    {
    fprintf
    (
    stdout,
    "for %.7e: len2 = %.7e, hypot = %.7e\n",
    x, len2(x, x), hypotf(x, x)
    );
    } /*compare_for*/

    int main(void)
    {
    compare_for(FLT_MAX / 2.0f);
    compare_for(2.0 / FLT_MAX);
    return
    0;
    } /*main*/

    Output:

    ldo@theon:c_try> !./
    ./naive_hypot
    for 1.7014117e+38: len2 = inf, hypot = 2.4061594e+38
    for 5.8774718e-39: len2 = 0.0000000e+00, hypot = 8.3120008e-39
    ldo@theon:c_try>

    How is it the standard library function is able to produce a reasonable-looking result where your function breaks down?


    its not breaking down, depend how you define breaking down for me for
    exampla sinf cosf or pow can be said are breaking don if thay count to
    much bits


    depending on application you may need long bit pattern accuracy or speed


    note btw i more meant lack od standarisation of names than this of implementations..implementations imo should be coherent but on a given platform not necessary among the different platforms

    if c needs the standard library have coherent implementation on
    different platforms (?) than i not talk on this library but scond
    kind of standarisation who want only coherency on given platform
    and maybe even not full coherency - the need is just for knowing which
    name is exactly for not to make babel mess
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Mon Sep 28 11:43:13 2026
    From Newsgroup: comp.lang.c

    On 28/09/2026 07:45, Lawrence DrCOOliveiro wrote:
    On Sun, 27 Sep 2026 20:04:20 +0200, fir wrote:

    float len2(float x,float y) { return sqrtf(x*x+y*y);}

    Interesting:

    /*
    Comparison of the na|>ve calculation of a triangle
    hypotenuse with the standard-library hypot(3) function.
    */

    #include <math.h>
    #include <values.h>
    #include <stdio.h>

    static float len2(float x,float y) { return sqrtf(x*x+y*y);}

    static void compare_for
    (
    float x
    )
    {
    fprintf
    (
    stdout,
    "for %.7e: len2 = %.7e, hypot = %.7e\n",
    x, len2(x, x), hypotf(x, x)
    );
    } /*compare_for*/


    This is a diabolic layout. I had to fix so that I can see what it was doing.

    How can you stretch a one-line function to this length?!

    int main(void)
    {
    compare_for(FLT_MAX / 2.0f);
    compare_for(2.0 / FLT_MAX);
    return
    0;
    } /*main*/

    Output:

    ldo@theon:c_try> !./
    ./naive_hypot
    for 1.7014117e+38: len2 = inf, hypot = 2.4061594e+38
    for 5.8774718e-39: len2 = 0.0000000e+00, hypot = 8.3120008e-39
    ldo@theon:c_try>

    How is it the standard library function is able to produce a reasonable-looking result where your function breaks down?

    You mean a reasonable looking result for quite unreasonable inputs?

    Because it's common to work with triangles whose sides are 170141173319264429905852091742258462720 units long!

    The simple function squares its arguments, so the upper limit for first
    test would be sqrt(FLT_MAX)/2.0 (since it also adds the two squares).

    In that case both versions give the same result. For second test, where
    you are working with triangles with non-zero sides smaller than
    Plancks's Constant, I haven't dealt with.

    Sure, the official version can deal with a wider range, but try it with FLT_MAX and both fail.

    In practice, for inputs this huge, it makes sense to switch to 'double'.

    Then it will also work better for arbitrary expressions that happen to
    use squares and other powers.

    So I think this overhead for 'hypot' is pointless, given that, in
    general, for any 'x' or type float, then x*x /anywhere in a program/
    will overflow when x is bigger than sqrt(FLT_MAX).

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Mon Sep 28 11:45:21 2026
    From Newsgroup: comp.lang.c

    On 28/09/2026 09:25, David Brown wrote:
    On 28/09/2026 01:53, bart wrote:

    Ones like MIN(x, y) can be considered fundamental, but not the length
    of a 2D vector which takes discrete X, Y float arguments.

    It also has a "hypot" function that returns, approximately, sqrt(x*x +
    y*y).

    fir's len2 function was one of a suite of functions familiar to me from
    3D graphics.

    If C's obscure 'hypot' function does that job, then great. My point was
    that that set of functions was too specific for a general purpose
    language at this level.

    But then, MSVCRT.DLL exports over 1300 functions, about the same number
    as SDL3!



    C has a string library.

    OK. I meant a higher level one!

    It's not very high level, compared to the
    support found in many other languages.

    I'm sure there are plenty of such libraries about. They don't need to
    be core language features at this level.


    Agreed.-a Things like "min", "abs", trig functions, etc., should normally not be core language features in any language unless the language is dedicated to numerical calculations.

    Many of these are available as machine instructions, so they are
    considered fundamental there. Some are available on my Casio.

    You think a cheap calculator should have sin() but not a programming
    language?

    Having them via user-functions in standard library is just about
    acceptable, but it's not ideal - see below for the machinations that are needed when you need to overload.

    One of fir's points, with which I agree, is that how C does it is a mess.

    Lots can be part of a standard
    library, however.-a There's no rule where the line should be drawn
    between standard libraries and additional libraries - that depends on
    the language.-a Since we are in c.l.c., the C standards show where the
    line is drawn in C.

    So why was hypot() ever added? Somebody thought it was a good idea at
    one time to add a such a one-line function?

    But then a one-line function is also trivial to write in user-code,
    compared to your own cos() for example.

    I wasn't aware of fmin etc. But they can't use the same name as there
    needs to be one function for each type.

    C has had type-generic maths macros since C99 - if you use #include <tgmath.h> and write "fabs(x)", then the appropriate real or complex floating point fabs, fabsf, fabsl, cabs, cabsf, cabsl function will be called.

    OK. I don't have tgmath.h in bcc, and tcc doesn't have it either. But
    I've looked at how it works in those that do. If I try this program:

    ly = sin(lx); // long double
    dy = sin(dx); // double
    fy = sin(fx); // float

    then lccwin32 preprocesses it to:

    ly = __sin(lx);
    dy = __sin(dx);
    fy = __sin(fx);

    Clang does:

    ly = __tg_sin((__typeof__(__tg_promote((lx))))(lx));
    dy = __tg_sin((__typeof__(__tg_promote((dx))))(dx));
    fy = __tg_sin((__typeof__(__tg_promote((fx))))(fx));

    And Gcc does:

    __builtin_tgmath (sinf, sin, sinl, csinf, csin, csinl, (lx))
    __builtin_tgmath (sinf, sin, sinl, csinf, csin, csinl, (dx))
    __builtin_tgmath (sinf, sin, sinl, csinf, csin, csinl, (fx))

    So it's not clear how the mechanism works. Compiler magic?

    With lccwin32 at least, it seems it implements an actual overloaded
    sin() in the form of __sin(), to distinguish from the underlying sin()
    in C which uses 'double'.

    But in practice, tgmath is used so rarely in open source code I've seen,
    that I've forgotten it existed.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Mon Sep 28 13:56:14 2026
    From Newsgroup: comp.lang.c

    On 28/09/2026 12:45, bart wrote:
    On 28/09/2026 09:25, David Brown wrote:
    On 28/09/2026 01:53, bart wrote:

    Ones like MIN(x, y) can be considered fundamental, but not the length
    of a 2D vector which takes discrete X, Y float arguments.

    It also has a "hypot" function that returns, approximately, sqrt(x*x +
    y*y).

    fir's len2 function was one of a suite of functions familiar to me from
    3D graphics.

    If C's obscure 'hypot' function does that job, then great. My point was
    that that set of functions was too specific for a general purpose
    language at this level.


    "hypot" - short for "hypotenuse" but easier to spell - is not obscure.
    It is a common name and part of the IEEE 754 standard. It makes a lot
    of sense for a language that is often used with code that requires
    conformance to that standard, to have support for the standard's
    required and recommended functions in its standard library. As Lawrence showed, proper implementations of such functions is not just a matter of copying the pure mathematical formula.

    But Fir could well have included other functions that are not likely to
    make sense in a standard library for a general-purpose programming
    language - and to have omitted many that should be there.


    But then, MSVCRT.DLL exports over 1300 functions, about the same number
    as SDL3!



    C has a string library.

    OK. I meant a higher level one!

    Standard C does not have a higher level string library than the string
    library C has in its standard library. No arguments there :-)

    More seriously - yes, C's string support is quite low-level.


    It's not very high level, compared to the support found in many other
    languages.

    I'm sure there are plenty of such libraries about. They don't need to
    be core language features at this level.


    Agreed.-a Things like "min", "abs", trig functions, etc., should
    normally not be core language features in any language unless the
    language is dedicated to numerical calculations.

    Many of these are available as machine instructions, so they are
    considered fundamental there. Some are available on my Casio.

    The majority of programming languages are defined in terms of an
    abstract machine - they are higher level than the processors that run
    them. So a function "sqrt" might be a single instruction on one target
    and a function call on another. It might depend on compiler flags too -
    some targets have such instruction for "normal" floating point numbers
    but need a library function to deal with denormals, NaNs, etc. It is up
    to the compiler and library implementation to handle all this correctly
    and efficiently. But the choice of supported instructions on a given processor should in no way be seen as a guide to what functions or
    operations are "fundamental", or what should be part of the core
    language (as keywords), or what should be part of a language standard
    library.


    You think a cheap calculator should have sin() but not a programming language?

    Of course.

    It is common to have "sin" as a standard library function in languages,
    but not as part of the core language itself. It is pointless having
    such functions in core language, taking up limited identifier space with
    a keyword that the solid majority of programs will never need. Put it
    in the library.


    Having them via user-functions in standard library is just about
    acceptable, but it's not ideal - see below for the machinations that are needed when you need to overload.

    I've had my own "sin" function in C programs. I do not remember that
    any complications were involved.


    One of fir's points, with which I agree, is that how C does it is a mess.

    Lots can be part of a standard library, however.-a There's no rule
    where the line should be drawn between standard libraries and
    additional libraries - that depends on the language.-a Since we are in
    c.l.c., the C standards show where the line is drawn in C.

    So why was hypot() ever added? Somebody thought it was a good idea at
    one time to add a such a one-line function?

    It is not a one-line function. Did you fail to read that bit of my
    post? My guess is that it was added to C (I have no idea when) because
    it is a recommended function for IEEE 754 floating point. It was
    probably added to the IEEE 754 standard because people thought it would
    be useful, and having it as a function defined as it is makes it more
    useful over a wider range, and with greater repeatability across platforms.


    But then a one-line function is also trivial to write in user-code,
    compared to your own cos() for example.

    I wasn't aware of fmin etc. But they can't use the same name as there
    needs to be one function for each type.

    C has had type-generic maths macros since C99 - if you use #include
    <tgmath.h> and write "fabs(x)", then the appropriate real or complex
    floating point fabs, fabsf, fabsl, cabs, cabsf, cabsl function will be
    called.

    OK. I don't have tgmath.h in bcc, and tcc doesn't have it either. But
    I've looked at how it works in those that do. If I try this program:

    -a-a-a ly = sin(lx);-a // long double
    -a-a-a dy = sin(dx);-a // double
    -a-a-a fy = sin(fx);-a // float

    then lccwin32 preprocesses it to:

    -a-a-a ly = __sin(lx);
    -a-a-a dy = __sin(dx);
    -a-a-a fy = __sin(fx);

    Clang does:

    -aly = __tg_sin((__typeof__(__tg_promote((lx))))(lx));
    -ady = __tg_sin((__typeof__(__tg_promote((dx))))(dx));
    -afy = __tg_sin((__typeof__(__tg_promote((fx))))(fx));

    And Gcc does:

    -a __builtin_tgmath (sinf, sin, sinl, csinf, csin, csinl, (lx))
    -a __builtin_tgmath (sinf, sin, sinl, csinf, csin, csinl, (dx))
    -a __builtin_tgmath (sinf, sin, sinl, csinf, csin, csinl, (fx))

    So it's not clear how the mechanism works. Compiler magic?

    The C standard says what is to be done, not how it is to be done. Until
    C11 there was no standard way to implement this kind of thing - so it
    was usually done with compiler extensions. The only requirement is that
    they are macros (letting people use #undef or #ifdef on them if they want).

    So a simple implementation would be :

    #define sin(x) sin(x)

    If "long double" is the same size and resolution as "double" on the
    platform, and it does not support complex numbers, that will work fine - albeit without any kind of speed gains for lower resolution.

    A C11 implementation might be :

    #define sin(x) \
    _Generic((x), \
    float : sinf, \
    double : sin, \
    long double : sinl, \
    float complex : csinf, \
    double complex : csin, \
    long double complex : csinl \
    )(x)

    The C99 <tgmath.h> header predates _Generic, so compiler extensions were
    used by more advanced compilers and libraries. I doubt if there is
    anything to be gained by changing existing libraries now, but a new implementation would probably use _Generic rather than inventing a
    compiler extension.


    With lccwin32 at least, it seems it implements an actual overloaded
    sin() in the form of __sin(), to distinguish from the underlying sin()
    in C which uses 'double'.

    With only the information you posted to go on, it looks more like a
    direct use of a single "__sin" function, but it is entirely possible
    that the compiler has some extensions that are not visible here. I
    don't know the details of lccwin32 - it is not a toolchain of interest
    to me.


    But in practice, tgmath is used so rarely in open source code I've seen, that I've forgotten it existed.


    Whether it is used or not in the code you have looked at is immaterial
    to its existence in the C standard, and how it provides a convenient and flexible form of "overloading" for such functions. It is your choice to implement it, or not, and to use it, or not - but it is silly to
    complain about multiple function names when the mechanism to avoid it is
    there and ready to use.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Mon Sep 28 14:16:03 2026
    From Newsgroup: comp.lang.c

    On 2026-09-28 12:45, bart wrote:
    On 28/09/2026 09:25, David Brown wrote:
    On 28/09/2026 01:53, bart wrote:

    Ones like MIN(x, y) can be considered fundamental, [...]

    *shrug* - In my practice I typically just implemented such primitive
    functions on the fly. - But what I'd find a lot more useful would be
    a generalized form, <numtype> max ([]<numtype> sequence) (where the
    simple case would then just be a special case).


    It also has a "hypot" function that returns, approximately, sqrt(x*x +
    y*y).

    [...]

    If C's obscure 'hypot' function does that job, then great.

    As far as memory serves, hypot() will even work in cases where the
    explicit primitive formula (as depicted above) would overflow.

    My point was
    that that set of functions was too specific for a general purpose
    language at this level.

    My opinion on that is that *most* functions are "too specific" as a
    _built-in_. That's what libraries are for! Pay only for what you use.

    There are general purpose language implementations that support such
    built-ins, though, depending on the environment - which makes these
    features de facto non-standard! - Kornshell's user-defined built-ins,
    for example. Or the Algol 68 Genie implementation, where you have all
    functions of, say, the GNU scientific library directly available if
    you compile that compiler with the GSL development package existing
    on your system.)

    [...]

    I'm sure there are plenty of such libraries about. They don't need to
    be core language features at this level.

    Exactly.


    Agreed.-a Things like "min", "abs", trig functions, etc., should
    normally not be core language features in any language unless the
    language is dedicated to numerical calculations.

    Well, it need not be numerical calculations. In Algol 68, for example,
    'abs' is also returning the ordinal number of a 'char' entity, or the
    numerical value for 'real' and 'int', and since it supports 'complex'
    it's also returning the complex 'abs' value (which, incidentally, is
    matching the above mentioned hypot() functionality).

    What is "normal" or not (in the core of a language) very much depends.


    Many of these are available as machine instructions, so they are
    considered fundamental there. Some are available on my Casio.

    I don't think "machine instructions" are a convincing criterion if
    you're thinking about language design on the user's level. (You said
    it yourself above.) Though if you're designing a language trimmed for performance (like "C") there might be a point (for some, not me) to
    have the low-level capabilities reflected in the language (as opposed
    to the higher-level abstractions).


    You think a cheap calculator should have sin() but not a programming language?

    My 45 years old Sharp calculator has for example arc-tan-hyperbolicus
    but I don't think that should be inherent part of a general purpose
    language in its language core (but certainly in some math library you
    can link). It has also some basic statistical primitives (that you'd
    have in some statistical math library that's usable in general purpose languages).

    That said; sine() is still widely considered as so basic that even
    some shell languages support it. - It would nonetheless be better
    placed in a math library than in the core language.

    (None of these are typically in CPUs' machine instructions. But some
    are available in math co-processors. - It shouldn't affect language
    design, though, IMO.)


    Having them via user-functions in standard library is just about
    acceptable, but it's not ideal - [...]

    That's most sensible, I'd rather say. (YMMV.)


    One of fir's points, with which I agree, is that how C does it is a mess.

    (We already widely know that fir and you are rabid about C's mess.)


    Lots can be part of a standard library, however.-a There's no rule
    where the line should be drawn between standard libraries and
    additional libraries - that depends on the language.-a Since we are in
    c.l.c., the C standards show where the line is drawn in C.

    So why was hypot() ever added? Somebody thought it was a good idea at
    one time to add a such a one-line function?

    Actually hypot() is documented in my 40+ years old Unix book (based
    on UNIX Version 7 and its legacy C-version), so we can probably say
    it was there since "the beginning" (and not so much "added at one
    time", even if the beginning is of course literally also "one time").


    But then a one-line function is also trivial to write in user-code,
    compared to your own cos() for example.

    Janis

    [...]

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Mon Sep 28 14:38:09 2026
    From Newsgroup: comp.lang.c

    On 28/09/2026 12:56, David Brown wrote:
    On 28/09/2026 12:45, bart wrote:
    On 28/09/2026 09:25, David Brown wrote:
    On 28/09/2026 01:53, bart wrote:

    Ones like MIN(x, y) can be considered fundamental, but not the
    length of a 2D vector which takes discrete X, Y float arguments.

    It also has a "hypot" function that returns, approximately, sqrt(x*x
    + y*y).

    fir's len2 function was one of a suite of functions familiar to me
    from 3D graphics.

    If C's obscure 'hypot' function does that job, then great. My point
    was that that set of functions was too specific for a general purpose
    language at this level.


    "hypot" - short for "hypotenuse" but easier to spell - is not obscure.
    It is a common name and part of the IEEE 754 standard.-a It makes a lot
    of sense for a language that is often used with code that requires conformance to that standard, to have support for the standard's
    required and recommended functions in its standard library.-a As Lawrence showed, proper implementations of such functions is not just a matter of copying the pure mathematical formula.

    He showed a way to avoid overflowing (with inputs above 10**19) if you
    can't be bothered to use a more appropriate type.

    However everywhere there is x*x in a program, or even x*y and x/y, there
    can be floating point overflow for certain values of x and y.

    You just have to be aware of what you are doing and know the limitations.

    It is common to have "sin" as a standard library function in languages,
    but not as part of the core language itself.-a It is pointless having
    such functions in core language, taking up limited identifier space with
    a keyword that the solid majority of programs will never need.-a Put it
    in the library.

    Disagree. Make it part of the core language and you get benefits:

    - Easier for a simple compiler to optimise for example

    - Easier to overload across numeric types

    - Always available without needing those annoying #includes (and is
    it math.h or float.h? I can never remember).

    - Not possible to override (in Python you can do math.sin = 342,
    in C it possible to either shadow or write a private 'sin')

    Downsides might be in not being able to create a function reference; it
    all depends on how the language works.

    taking up limited identifier space with

    See my last point - you don't /want/ user programs to use 'sin'!

    As for limited identifier space, AFAICS that is essentially unlimited.

    I've had my own "sin" function in C programs.-a I do not remember that
    any complications were involved.

    The usual approach for a custom version is to use a slightly different
    name. I dislike overriding or shadowing built-ins.

    (Funny how shadowing or overriding is usually perceived as bad, until
    you want to shadow something like 'sin' then it's a must-have!)


    One of fir's points, with which I agree, is that how C does it is a mess.

    Lots can be part of a standard library, however.-a There's no rule
    where the line should be drawn between standard libraries and
    additional libraries - that depends on the language.-a Since we are in
    c.l.c., the C standards show where the line is drawn in C.

    So why was hypot() ever added? Somebody thought it was a good idea at
    one time to add a such a one-line function?

    It is not a one-line function.-a Did you fail to read that bit of my
    post?

    I did then I misremembered it as being from LD'O's post which I replied to.

    I just tried a test program that compared the official hypot() to a
    one-line version using random floats, and I have yet to detect a
    difference across 100 million tests.

    (Float ranges were 0.0 to 10**150 approx using f64 type. However this
    would be MSVCRT's hypot() so maybe it is also simple.)

    With lccwin32 at least, it seems it implements an actual overloaded
    sin() in the form of __sin(), to distinguish from the underlying sin()
    in C which uses 'double'.

    With only the information you posted to go on, it looks more like a
    direct use of a single "__sin" function, but it is entirely possible
    that the compiler has some extensions that are not visible here.-a I
    don't know the details of lccwin32 - it is not a toolchain of interest
    to me.

    It seems that __sin is nothing special: it is implemented using x86's
    'fsin' hardware instruction. That means f32 types have to be widened and
    the result then narrowed as needed.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Mon Sep 28 16:12:20 2026
    From Newsgroup: comp.lang.c

    On 28/09/2026 15:38, bart wrote:
    On 28/09/2026 12:56, David Brown wrote:
    On 28/09/2026 12:45, bart wrote:
    On 28/09/2026 09:25, David Brown wrote:
    On 28/09/2026 01:53, bart wrote:

    Ones like MIN(x, y) can be considered fundamental, but not the
    length of a 2D vector which takes discrete X, Y float arguments.

    It also has a "hypot" function that returns, approximately, sqrt(x*x
    + y*y).

    fir's len2 function was one of a suite of functions familiar to me
    from 3D graphics.

    If C's obscure 'hypot' function does that job, then great. My point
    was that that set of functions was too specific for a general purpose
    language at this level.


    "hypot" - short for "hypotenuse" but easier to spell - is not obscure.
    It is a common name and part of the IEEE 754 standard.-a It makes a lot
    of sense for a language that is often used with code that requires
    conformance to that standard, to have support for the standard's
    required and recommended functions in its standard library.-a As
    Lawrence showed, proper implementations of such functions is not just
    a matter of copying the pure mathematical formula.

    He showed a way to avoid overflowing (with inputs above 10**19) if you
    can't be bothered to use a more appropriate type.

    He showed that the way to avoid overflowing is to use the standard
    library "hypot" function instead of an amateur version. It applies to
    all floating point types. And there may be other issues that it gets
    right, such as rounding or treatment of NaNs which are relevant. People
    who care about the quality of their floating point work care about this
    sort of thing - it means they don't lose as much accuracy when doing
    lots of calculations. If you don't care, that's okay (I have never been particularly bothered for my own code), but it is important to many
    other programmers.


    However everywhere there is x*x in a program, or even x*y and x/y, there
    can be floating point overflow for certain values of x and y.

    You just have to be aware of what you are doing and know the limitations.


    It is more complicated than that for floating point. Numerical
    stability, portability and repeatability is not an easy matter. For
    simpler uses, it is often just a matter of making sure you have types
    that fit for the ranges and accuracy you need at the time. But for
    standard library functions, you have to do a lot better, because not all
    uses are simple.

    It is common to have "sin" as a standard library function in
    languages, but not as part of the core language itself.-a It is
    pointless having such functions in core language, taking up limited
    identifier space with a keyword that the solid majority of programs
    will never need.-a Put it in the library.

    Disagree. Make it part of the core language and you get benefits:

    - Easier for a simple compiler to optimise for example

    Serious C compilers don't have a problem there. The effort involved for compiler writers is considered a very minor priority in defining
    languages and libraries.


    - Easier to overload across numeric types

    C manages it without trouble.


    - Always available without needing those annoying #includes (and is
    -a it math.h or float.h? I can never remember).

    Other C programmers manage that without effort.


    - Not possible to override (in Python you can do math.sin = 342,
    -a in C it possible to either shadow or write a private 'sin')


    This is a good thing. C programmers can (though most don't bother)
    choose different standard libraries for different balances of features
    like size and speed. Individual library functions can be replaced.

    Downsides might be in not being able to create a function reference; it
    all depends on how the language works.

    taking up limited identifier space with

    See my last point - you don't /want/ user programs to use 'sin'!

    Other people /do/ want to be able to make their own "sin" function. And
    there are /lots/ of functions in the C standard libraries. There are
    plenty of real-world programs where program identifiers match some
    standard library identifiers - and more so, as new functions are added.
    Your technique might be acceptable for a small, limited language that is
    never going to change - but not for a more serious language where the
    language and library needs to be able to grow while minimising conflicts
    with existing code.


    As for limited identifier space, AFAICS that is essentially unlimited.


    Don't be silly.

    I've had my own "sin" function in C programs.-a I do not remember that
    any complications were involved.

    The usual approach for a custom version is to use a slightly different
    name. I dislike overriding or shadowing built-ins.


    Your "usual approach" and what you like or dislike is no indication of
    what other people may do. There are reasons why I would sometimes pick
    a name that is different from the standard library name, and reasons
    while I would sometimes pick the same name.

    (Funny how shadowing or overriding is usually perceived as bad, until
    you want to shadow something like 'sin' then it's a must-have!)


    It is not a "must-have", it is a convenience. Of course it's possible
    to work in a language where "sin" is a built-in function that is fixed
    in the language. But it usually has no benefit, and just disadvantages compared to using a standard library. That's why few languages since
    BASIC have gone your route.

    Anyway, this is C - "sin" is never going to be part of the language, it
    is always going to be in the standard library. And people can use it
    for any floating point type, with as much efficiency as the library can muster.


    One of fir's points, with which I agree, is that how C does it is a
    mess.

    Lots can be part of a standard library, however.-a There's no rule
    where the line should be drawn between standard libraries and
    additional libraries - that depends on the language.-a Since we are
    in c.l.c., the C standards show where the line is drawn in C.

    So why was hypot() ever added? Somebody thought it was a good idea at
    one time to add a such a one-line function?

    It is not a one-line function.-a Did you fail to read that bit of my post?

    I did then I misremembered it as being from LD'O's post which I replied to.


    OK.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c on Mon Sep 28 11:03:18 2026
    From Newsgroup: comp.lang.c

    On 2026-09-28 02:45, Lawrence DrCOOliveiro wrote:
    On Sun, 27 Sep 2026 20:04:20 +0200, fir wrote:

    float len2(float x,float y) { return sqrtf(x*x+y*y);}

    Interesting:

    /*
    Comparison of the na|>ve calculation of a triangle
    hypotenuse with the standard-library hypot(3) function.
    */

    #include <math.h>
    #include <values.h>
    #include <stdio.h>

    static float len2(float x,float y) { return sqrtf(x*x+y*y);}

    static void compare_for
    (
    float x
    )
    {
    fprintf
    (
    stdout,
    "for %.7e: len2 = %.7e, hypot = %.7e\n",
    x, len2(x, x), hypotf(x, x)
    );
    } /*compare_for*/

    int main(void)
    {
    compare_for(FLT_MAX / 2.0f);
    compare_for(2.0 / FLT_MAX);
    return
    0;
    } /*main*/

    Output:

    ldo@theon:c_try> !./
    ./naive_hypot
    for 1.7014117e+38: len2 = inf, hypot = 2.4061594e+38
    for 5.8774718e-39: len2 = 0.0000000e+00, hypot = 8.3120008e-39
    ldo@theon:c_try>

    How is it the standard library function is able to produce a reasonable-looking result where your function breaks down?

    See
    <https://en.wikipedia.org/wiki/Pythagorean_addition#Calculation_order>
    for details about how that can be achieved.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c on Mon Sep 28 11:15:32 2026
    From Newsgroup: comp.lang.c

    On 28/09/2026 12:45, bart wrote:
    On 28/09/2026 09:25, David Brown wrote:
    It also has a "hypot" function that returns, approximately,
    sqrt(x*x +
    y*y).
    So why was hypot() ever added? Somebody thought it was a good idea at
    one time to add a such a one-line function?
    It was part of the major expansion to the <math.h> library that occurred
    in C99. It was added because of the "without undue overflow or
    underflow." requirement. Achieving that result makes it a bit more
    complicated than just a one-line function. Also, even most people who
    are well aware of that problem are unaware of how best to avoid it. See <https://en.wikipedia.org/wiki/Pythagorean_addition#Calculation_order>
    for more details.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@profesor.fir@gmail.com to comp.lang.c on Mon Sep 28 17:22:23 2026
    From Newsgroup: comp.lang.c

    David Brown pisze:

    But Fir could well have included other functions that are not likely to
    make sense in a standard library for a general-purpose programming
    language - and to have omitted many that should be there.

    those ones for sure have sense in very general library - i use them a lot

    float dist2_square(float x1,float y1,float x2,float y2) { float x=x2-x1,y=y2-y1; return x*x+y*y; }
    float dist2(float x1,float y1,float x2,float y2) { return sqrtf(dist2(x1,y1,x2,y2));}
    float len2_square(float x,float y) { return x*x+y*y; }
    float len2(float x,float y) { return sqrtf(x*x+y*y);}
    float dot2(float ax,float ay,float bx,float by){ return ax*bx+ay*by;}
    float cross2(float ax,float ay,float bx,float by){ return ax*by-ay*bx;}
    void norm2(float *x,float *y) { float d=sqrtf(*x**x+*y**y); if(d>0)
    { *x/=d; *y/=d; }}
    float dist2_to_line(float px,float py,float ax,float ay,float bx,float
    by){ return fabsf(cross2(bx-ax,by-ay,px-ax,py-ay)) /sqrtf(dist2_square(ax,ay,bx,by));}


    the question i stated is not it if have sense or ot but just to agree
    for names

    for example those names above are quite random and people i gues state
    random names her and there is needed of agreement on those "official"
    ones

    puting their implementation in c-lib is one way of doing that but
    there are other ways for example produce a paper with offiical
    recomandations for names of those,
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Mon Sep 28 16:40:05 2026
    From Newsgroup: comp.lang.c

    On 28/09/2026 16:15, James Kuyper wrote:
    On 28/09/2026 12:45, bart wrote:
    On 28/09/2026 09:25, David Brown wrote:
    It also has a "hypot" function that returns, approximately,
    sqrt(x*x +
    y*y).
    So why was hypot() ever added? Somebody thought it was a good idea at
    one time to add a such a one-line function?
    It was part of the major expansion to the <math.h> library that occurred
    in C99. It was added because of the "without undue overflow or
    underflow." requirement. Achieving that result makes it a bit more complicated than just a one-line function. Also, even most people who
    are well aware of that problem are unaware of how best to avoid it. See <https://en.wikipedia.org/wiki/Pythagorean_addition#Calculation_order>
    for more details.

    I think most will be vaguely aware of such problems, but usually they
    don't matter because they only happen with unlikely, extreme inputs.

    One simple way around in this case, is to use 64-bit floats for the calculation, even if the inputs are 32-bits.

    That might kick the can down the road enough that overflows will
    virtually never occur (eg. it might need inputs over 10**150, and that I
    think is impossible if inputs were promoted from 32 bits).

    I'm less familiar with underflows, ie. values smaller than around
    10e-308, but I think the same applies.

    The technique demonstrated in LD'O's post I think buys you one more bit
    of exponent range (although the article you linked to seems to suggest
    you can go beyond that with extra scaling).

    When such things used to be important to me, I tried to avoid doing the square-root part anyway, for example I would compare one set of x*x +
    y*y with another. In that case it is necessary to express the full
    magnitude.

    If the values represent length, then another approach would be a choice
    of units. I liked using mm, but if expressed in metres, then I think
    that's another 10 extra bits of binary exponent range, unless the issue
    is underflow, then it might make it worse!

    In any case, it was NEVER a problem (well, until someone zoomed in
    enough within my CAD product that they hit the limitations of the
    floating point representation. Things would get jerky).

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@profesor.fir@gmail.com to comp.lang.c on Mon Sep 28 17:50:05 2026
    From Newsgroup: comp.lang.c

    fir pisze:
    fir pisze:
    you know there are a lacking tiny functions in c-lib
    (by c-lib i mean those standard c includes all know)

    AND if people use many maybe there is a need to standarize it
    byslef? if you need some could be ggood candidates for standarisation
    maybe write it here (i mean whole body of such function)

    we could and should discuss them


    maybe something liek this?


    int mini(int a,int b) { return a<b?a:b; }
    int maxi(int a,int b) { return a>b?a:b; }
    float minf(float a,float b) { return a<b?a:b; }
    float maxf(float a,float b) { return a>b?a:b; }
    int absi(int x) { return x<0?-x:x; }
    float absf(float x) { return x<0?-x:x; }
    float signf(float x) { return x>0?1:x<0?-1:0; }
    int signi(int x) { return x>0?1:x<0?-1:0; }

    //above controversial?

    int clampi(int x,int a,int b) { return x<a?a:x>b?b:x; }
    float clampf(float x,float a,float b) { return x<a?a:x>b?b:x; }
    int betweeni(int x,int a,int b) {-a return x>=a && x<=b; }

    float lerp(float a,float b,float t) { return a+(b-a)*t; }
    float inv_lerp(float a,float b,float x) { return (x-a)/(b-a); }
    float remap(float x,float a,float b,float c,float d) { return c+(x-a)*(d-c)/(b-a); }
    float rad(float x) { return x*PI/180.0f; }
    float deg(float x) { return x*180.0f/PI; }

    //thise above i dont quite use

    float dist2_square(float x1,float y1,float x2,float y2) {-a-a float x=x2-x1,y=y2-y1;-a-a-a-a return x*x+y*y; }
    float dist2(float x1,float y1,float x2,float y2) {-a-a-a return sqrtf(dist2(x1,y1,x2,y2));}
    float len2_square(float x,float y) {-a-a-a return x*x+y*y; }
    float len2(float x,float y) {-a return sqrtf(x*x+y*y);}
    float dot2(float ax,float ay,float bx,float by){-a-a return ax*bx+ay*by;} float cross2(float ax,float ay,float bx,float by){-a-a-a return ax*by-ay*bx;} void-a norm2(float *x,float *y) {-a float d=sqrtf(*x**x+*y**y);-a-a if(d>0) { *x/=d;-a *y/=d; }}
    float dist2_to_line(float px,float py,float ax,float ay,float bx,float by){-a-a-a return fabsf(cross2(bx-ax,by-ay,px-ax,py-ay)) /sqrtf(dist2_square(ax,ay,bx,by));}

    // hare names may be controversial

    the fact is imo though people should generallu decide and use one set of such names imo

    there is also more functions to put here


    NOTE what i say/ask here also has a quite practical dimension as i
    revrite somewhat my old green file library and i may revrite the
    basic functions and need to chose them.. mostly its about the names
    though not only

    for example i not sure for rand functions i consider some like that

    int randi(int n) {return rand() % (n + 1);}
    int randi2(int a, int b) { return a + rand() % (b - a + 1);}
    float randf(float a) { return a*(float)rand() / (float)RAND_MAX; }
    float randf2(float a, float b) { return a + randf( b - a);}

    /* rand: return pseudo-random integer on 0..32767 */
    enum {FRAND_MAX = 32767};
    unsigned long int frand_next = 1;
    int frand(void) { frand_next = frand_next * 1103515245 + 12345;
    return (unsigned int)(frand_next/65536) % 32768; }
    void frand_seed(unsigned int seed) { frand_next = seed; }

    int frandi(int n) {return frand() % (n + 1);}
    int frandi2(int a, int b) { return a + frand() % (b - a + 1);}
    float frandf(float a) { return a*(float)frand() / (float)FRAND_MAX; }
    float frandf2(float a, float b) { return a + frandf(b-a);}


    those fast rand i not much tested unly roughly and the advantage is
    this frand() seem to be almost 10x faster than std c rand()

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Mon Sep 28 16:52:06 2026
    From Newsgroup: comp.lang.c

    On 28/09/2026 15:12, David Brown wrote:
    On 28/09/2026 15:38, bart wrote:

    As for limited identifier space, AFAICS that is essentially unlimited.


    Don't be silly.

    But you brought it up!
    I've had my own "sin" function in C programs.-a I do not remember that
    any complications were involved.

    The usual approach for a custom version is to use a slightly different
    name. I dislike overriding or shadowing built-ins.


    Your "usual approach" and what you like or dislike is no indication of
    what other people may do.-a There are reasons why I would sometimes pick
    a name that is different from the standard library name, and reasons
    while I would sometimes pick the same name.

    (Funny how shadowing or overriding is usually perceived as bad, until
    you want to shadow something like 'sin' then it's a must-have!)


    It is not a "must-have", it is a convenience.-a Of course it's possible
    to work in a language where "sin" is a built-in function that is fixed
    in the language.-a But it usually has no benefit, and just disadvantages compared to using a standard library.-a That's why few languages since
    BASIC have gone your route.

    Yes, I know, most languages prefer to have things in libraries rather
    than in the core.

    Some even want to have basics such as statements in libraries (Clisp was mentioned but this stuff is popular in esolangs).

    But one example where built-in is better is with Print. Otherwise this presents challenges to do in user-code:

    * Variable-length set of arguments

    * Mixed argument types

    * Optional per-item information

    * Optional per-print information (eg. destination)

    * Less than ideal syntax


    In C, this meant several things:

    * Needing to add stdio.h each time

    * Having to introduce variadic functions (possibly just for this reason)

    * Less type safety

    * Using format codes to import type information

    Other languages have their own problems in fitting those requirements to standard functions


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Mon Sep 28 18:49:54 2026
    From Newsgroup: comp.lang.c

    On 28/09/2026 17:52, bart wrote:
    On 28/09/2026 15:12, David Brown wrote:
    On 28/09/2026 15:38, bart wrote:

    As for limited identifier space, AFAICS that is essentially unlimited.


    Don't be silly.

    But you brought it up!

    The global name space for "easy" names like "sin" or "min" is limited. Conflicts are likely if the language claims them for itself. That's
    obvious. The global name space for names of any kind is not limited.
    That's equally obvious.

    I've had my own "sin" function in C programs.-a I do not remember
    that any complications were involved.

    The usual approach for a custom version is to use a slightly
    different name. I dislike overriding or shadowing built-ins.


    Your "usual approach" and what you like or dislike is no indication of
    what other people may do.-a There are reasons why I would sometimes
    pick a name that is different from the standard library name, and
    reasons while I would sometimes pick the same name.

    (Funny how shadowing or overriding is usually perceived as bad, until
    you want to shadow something like 'sin' then it's a must-have!)


    It is not a "must-have", it is a convenience.-a Of course it's possible
    to work in a language where "sin" is a built-in function that is fixed
    in the language.-a But it usually has no benefit, and just
    disadvantages compared to using a standard library.-a That's why few
    languages since BASIC have gone your route.

    Yes, I know, most languages prefer to have things in libraries rather
    than in the core.

    So perhaps it's a good idea?


    Some even want to have basics such as statements in libraries (Clisp was mentioned but this stuff is popular in esolangs).

    I am not sure what you mean by "having statements in libraries". In
    some languages, it is possible to define control structures in the
    language itself. It is natural to use the language - and therefore a
    standard library - for things that can be written in the language, as
    long as there are no efficiency issues.


    But one example where built-in is better is with Print. Otherwise this presents challenges to do in user-code:

    No, "print" is not "better" as a built-in. That's pure bias on your part.

    Lots of programs have little or no use for "print", or they need
    something significantly different (showing messages in a dialog box,
    printing them to logs or serial ports, etc.). Making it special is not
    a good idea.


    * Variable-length set of arguments

    * Mixed argument types

    * Optional per-item information

    * Optional per-print information (eg. destination)

    * Less than ideal syntax


    These can all be handled in a language-definable function, and do not
    need special handling. Different systems have their pros and cons, of
    course.


    In C, this meant several things:

    * Needing to add stdio.h each time

    * Having to introduce variadic functions (possibly just for this reason)

    * Less type safety

    * Using format codes to import type information

    Other languages have their own problems in fitting those requirements to standard functions

    If you want something complex, it is complex.

    All you do by having it as a special built-in feature of the language is limited its usefulness, and mean that people have to re-invent it anyway.

    I understand your style of thinking - it's the way people thought about programming language forty-odd years ago.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Mon Sep 28 20:26:46 2026
    From Newsgroup: comp.lang.c

    On 28/09/2026 17:49, David Brown wrote:
    On 28/09/2026 17:52, bart wrote:

    Yes, I know, most languages prefer to have things in libraries rather
    than in the core.

    So perhaps it's a good idea?

    IS it a good idea? Or is it just what is commonly done and people go
    along with it?

    I always find it odd when people strive to keep a core language to a few
    dozen keywords to reduce 'cognitive load', but are fine with needing to
    use a library that exports a thousand identifiers, all in the same
    namespace.


    But one example where built-in is better is with Print. Otherwise this
    presents challenges to do in user-code:

    No, "print" is not "better" as a built-in.-a That's pure bias on your part.
    The examples below suggest otherwise.



    Lots of programs have little or no use for "print", or they need
    something significantly different (showing messages in a dialog box, printing them to logs or serial ports, etc.

    So they /are/ using Print, which still has a variety of uses:

    * To send output to such log files

    * To format data

    * To write such data to strings, perhaps might then be displayed in a
    GUI

    * To turn binary data into text or stringify in general

    * To write line-based text files in general

    * To print to actual printers (eg. narrow receipt printers which i have
    used extensively)

    Such things are still very much needed.

    These can all be handled in a language-definable function, and do not
    need special handling.

    No, they usually can't. Functions generally take a fixed number of
    parameters, and in a typed language, they are also usually a fixed type.

    Here is a task that prints an integer 'i', and its square root, followed
    by a newline, to the console, in several languages:

    Zig: std.debug.print("{} {}\n",.{i,@sqrt(@as(f64,@floatFromInt(i)))});

    C: printf("%d %f\n", i, sqrt(i));

    C++: std::cout << i << " " << sqrt(i) << std::endl;

    M: println i, sqrt i

    BASIC: 10 PRINT I, SQR(I)

    The first three all need prerequisites to make it work. The last two
    need nothing, not even variadic functions.

    Maybe it's a coincidence that both have Print and Sqrt as built-ins.

    Other languages have their own problems in fitting those requirements
    to standard functions

    If you want something complex, it is complex.

    All you do by having it as a special built-in feature of the language is limited its usefulness, and mean that people have to re-invent it anyway.

    I understand your style of thinking - it's the way people thought about programming language forty-odd years ago.

    More like 50 years. But yes, when things were simple: see my examples
    above. So what the hell happened?

    Here's another example that current languages suck at: wait for a line
    of input and read 3 numbers from it:

    readln a, b, c

    I can't show you the C - I'd have to go and look it up! And I'd have to
    ensure the behaviour was line-based rather than stream-based.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Mon Sep 28 15:30:39 2026
    From Newsgroup: comp.lang.c

    On 9/28/2026 7:12 AM, David Brown wrote:
    [...]

    Fwiw, fun times! :^)

    https://forums.parallax.com/discussion/147522/dog-leg-hypotenuse-approximation


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Mon Sep 28 17:24:09 2026
    From Newsgroup: comp.lang.c

    David Brown <david.brown@hesbynett.no> writes:
    [...]
    It is not a one-line function. Did you fail to read that bit of my
    post? My guess is that it was added to C (I have no idea when)

    hypot(), hypotf(), and hypotl() were added in C99, along with the
    type-generic macro hypot() in <tgmath.h>.

    [...]

    A C11 implementation might be :

    #define sin(x) \
    _Generic((x), \
    float : sinf, \
    double : sin, \
    long double : sinl, \
    float complex : csinf, \
    double complex : csin, \
    long double complex : csinl \
    )(x)

    That wouldn't be conforming. The sin() macro with an argument of an
    integer type has to work, converting the argument to double.

    Handling that correctly and emitting sensible error messages for things
    like sin("foo") is difficult if the implementation uses _Generic,
    which is why some implementations use compiler "magic".

    (tcc uses _Generic for this -- and it appears to have a bug whereby
    sin("foo") is not diagnosed and produces a garbage result).

    [...]
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Tue Sep 29 00:58:20 2026
    From Newsgroup: comp.lang.c

    On Mon, 28 Sep 2026 12:42:31 +0200, fir wrote:

    its not breaking down, depend how you define breaking down for me
    for exampla sinf cosf or pow can be said are breaking don if thay
    count to much bits

    Your code breaks down because it cannot produce a result which is
    perfectly representable within the implementation range.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Tue Sep 29 01:00:10 2026
    From Newsgroup: comp.lang.c

    On Mon, 28 Sep 2026 11:43:13 +0100, bart wrote:

    You mean a reasonable looking result for quite unreasonable inputs?

    WhatrCOs rCLunreasonablerCY about it? ItrCOs called rCLfloating pointrCY precisely
    because it is capable of covering such a wide dynamic range. And the
    answers in those cases are also within the representable dynamic
    range. And there are ways of computing those answers, which the na|>ve calculation completely fails to do.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@profesor.fir@gmail.com to comp.lang.c on Tue Sep 29 03:02:47 2026
    From Newsgroup: comp.lang.c

    Lawrence DrCOOliveiro pisze:
    On Mon, 28 Sep 2026 12:42:31 +0200, fir wrote:

    its not breaking down, depend how you define breaking down for me
    for exampla sinf cosf or pow can be said are breaking don if thay
    count to much bits

    Your code breaks down because it cannot produce a result which is
    perfectly representable within the implementation range.


    LOL, im not sure if i understand this above sentence but for me code is
    broken if its too slow not when it present exact same graphics just faster
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Tue Sep 29 03:16:57 2026
    From Newsgroup: comp.lang.c

    On Tue, 29 Sep 2026 03:02:47 +0200, fir wrote:

    Lawrence DrCOOliveiro pisze:

    On Mon, 28 Sep 2026 12:42:31 +0200, fir wrote:

    its not breaking down, depend how you define breaking down for me
    for exampla sinf cosf or pow can be said are breaking don if thay
    count to much bits

    Your code breaks down because it cannot produce a result which is
    perfectly representable within the implementation range.

    LOL, im not sure if i understand this above sentence but for me code
    is broken if its too slow not when it present exact same graphics
    just faster

    DoesnrCOt correctness of the code figure into your thinking?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Tue Sep 29 06:38:32 2026
    From Newsgroup: comp.lang.c

    On Mon, 28 Sep 2026 11:45:21 +0100, bart wrote:

    If C's obscure 'hypot' function does that job, then great.

    Nothing obscure about it. Every language with a decent maths library
    has it. To name but a few:
    <https://cppreference.com/cpp/numeric/math/hypot> <https://docs.python.org/3/library/math.html#math.hypot> <https://crates.io/crates/core_maths/0.1.1/code/src/lib.rs> <https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/lang/Math.java>

    Why? Because <https://en.wikipedia.org/wiki/IEEE_754>. WerCOve already discussed elsewhere why implementing it correctly is somewhat
    nontrivial, because the obvious na|>ve implementation is prone to be
    ... somewhat fragile.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Tue Sep 29 09:03:37 2026
    From Newsgroup: comp.lang.c

    On 2026-09-28 16:12, David Brown wrote:
    On 28/09/2026 15:38, bart wrote:

    - Always available without needing those annoying #includes (and is
    -a-a it math.h or float.h? I can never remember).

    Other C programmers manage that without effort.

    I seem to recall that on his platform there's no man-pages.
    (Or that he, maybe, dislikes looking into the documentation?
    Sometime he gives that impression.)


    (Funny how shadowing or overriding is usually perceived as bad, until
    you want to shadow something like 'sin' then it's a must-have!)

    Since when is shadowing (or "overriding" in its various forms)
    "perceived as bad"? - I've always seen it as a useful feature.
    And never heard anyone complaining about it. In decades I also
    don't recall that subtile (or obvious) errors had been reported
    because of that. (Are you, yet again, just making things up for
    the argument or have you any different observations from your
    personal coding practice?)

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Tue Sep 29 07:08:03 2026
    From Newsgroup: comp.lang.c

    On Mon, 28 Sep 2026 14:38:09 +0100, bart wrote:

    On 28/09/2026 12:56, David Brown wrote:

    "hypot" - short for "hypotenuse" but easier to spell - is not
    obscure. It is a common name and part of the IEEE 754 standard.-a It
    makes a lot of sense for a language that is often used with code
    that requires conformance to that standard, to have support for the
    standard's required and recommended functions in its standard
    library.-a As Lawrence showed, proper implementations of such
    functions is not just a matter of copying the pure mathematical
    formula.

    He showed a way to avoid overflowing (with inputs above 10**19) if
    you can't be bothered to use a more appropriate type.

    I knew somewhat would try to make this claim, sooner or later. So
    hererCOs a long-double version -- I donrCOt think GCC supports any floating-point formats with greater range or precision than this!

    /*
    Comparison of the na|>ve calculation of a triangle
    hypotenuse with the standard-library hypot(3) function.
    */

    #include <math.h>
    #include <values.h>
    #include <stdio.h>

    static long double len2(long double x,long double y) { return sqrtl(x*x+y*y);}

    static void compare_for
    (
    long double x
    )
    {
    fprintf
    (
    stdout,
    "for %.7Le: len2 = %.7Le, hypot = %.7Le\n",
    x, len2(x, x), hypotl(x, x)
    );
    } /*compare_for*/

    int main(void)
    {
    compare_for(LDBL_MAX / 2.0);
    compare_for(2.0 / LDBL_MAX);
    return
    0;
    } /*main*/

    Output:

    ldo@theon:c_try> ./naive_hypot_long_double
    for 5.9486575e+4931: len2 = inf, hypot = 8.4126721e+4931
    for 1.6810516e-4932: len2 = 0.0000000e+00, hypot = 2.3773659e-4932

    So the library routine is still capable of producing meaningful results,
    while the na|>ve implementation still breaks down.

    Any more nitpicks?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Tue Sep 29 07:10:03 2026
    From Newsgroup: comp.lang.c

    On Mon, 28 Sep 2026 16:52:06 +0100, bart wrote:

    But one example where built-in is better is with Print. Otherwise
    this presents challenges to do in user-code:

    ThatrCOs just a language limitation. Python can do it type-safely.

    And if you think thatrCOs an unfair example, Algol 68 also worked out a
    way to implement variadic/polymorphic functions in a type-safe manner.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Tue Sep 29 09:28:25 2026
    From Newsgroup: comp.lang.c

    On 2026-09-28 18:49, David Brown wrote:
    On 28/09/2026 17:52, bart wrote:

    But one example where built-in is better is with Print. Otherwise this
    presents challenges to do in user-code:

    The last "prominent" languages with a built-in 'print' I recall to have
    used were BASIC, and Awk. (Other languages I used, starting with Pascal,
    Algol 68, C/C++, Shell, etc. had just predefined functions that are
    defined in the program environment and that could (whether it makes
    sense or not) be replaced and shadowed. YMMV. - What modern languages -
    I'm not asking for any of your irrelevant personal designed languages -
    have that built-in in the language? I'm curious.)

    The historically strangest language definition in that respect was IIRC
    Algol 60, where initially no I/O had been standardized at all; that was
    defined by the various language implementations independently depending
    on the platform.

    No, "print" is not "better" as a built-in.-a That's pure bias on your part.

    Janis

    [...]

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Tue Sep 29 09:45:33 2026
    From Newsgroup: comp.lang.c

    On 28/09/2026 21:26, bart wrote:
    On 28/09/2026 17:49, David Brown wrote:
    On 28/09/2026 17:52, bart wrote:

    Yes, I know, most languages prefer to have things in libraries rather
    than in the core.

    So perhaps it's a good idea?

    IS it a good idea? Or is it just what is commonly done and people go
    along with it?

    Putting functions in standard libraries is commonly done because it is a
    good idea.

    Very occasionally, in some field of thought, someone will come along
    with a crazy idea that is different from the way everyone else does
    things, and their new way is revolutionary and changes the field
    forever. When Alfred Wegener proposed his theory of plate tectonics,
    all the other geologists laughed at him and said he was being
    ridiculous. It turned out he was right.

    Most of the time, when one person thinks differently from everyone else,
    that one person is wrong. They have misunderstood the situation, or are thinking only of a very limited case.

    And here you are not coming with new ideas. You are coming with ideas
    that were used in the early days of programming language design - things
    other language designers knew about and grew out of, things that they
    had to use when computers were small and space was tight but that they
    could put behind them once they had the resources to make better languages.

    Keeping everything in a core language still has its place, in small
    teaching languages, macro languages, and limited domain-specific languages.

    You have a small, limited domain-specific language - the domain is one language designer, one toolchain developer, one toolchain user. That is
    very niche, and gives the very special situation that the cost of adding
    a function to the application code, standard library, or language and toolchain is all the same. If that works for you, that's fine - enjoy yourself. But you need to realise that it is not applicable outside
    such a very specific situation.


    I always find it odd when people strive to keep a core language to a few dozen keywords to reduce 'cognitive load', but are fine with needing to
    use a library that exports a thousand identifiers, all in the same namespace.

    It can seem odd because you have misunderstood - you are wrong on all
    counts here.

    First, keeping a core language small has many purposes - lower cognitive
    load to learn it may or may not be one of them. Many languages have
    complex cores with lots of features, but still have as much as possible
    pushed over to standard libraries.

    Secondly, people do not need to learn everything in the language's
    standard libraries. I do not know all the details of more than a small
    part of the functions and macros in the C standard library. And that
    fraction is tiny for languages with bigger libraries, like C++ or Python.

    Thirdly, modern languages do not put all the identifiers in the same namespace. C is older and does not have namespaces, but even there you
    have some control by choosing which headers to include or not.



    But one example where built-in is better is with Print. Otherwise
    this presents challenges to do in user-code:

    No, "print" is not "better" as a built-in.-a That's pure bias on your
    part.
    The examples below suggest otherwise.


    No. You are extrapolating your own needs and preferences and assuming
    that they apply everywhere.



    Lots of programs have little or no use for "print", or they need
    something significantly different (showing messages in a dialog box,
    printing them to logs or serial ports, etc.

    So they /are/ using Print, which still has a variety of uses:


    No, they are not.

    They are doing /related/ tasks, but not the kind of thing you get from a "print" statement in BASIC.

    If "print" is a fixed, special built-in feature of the language, then it
    is not flexible enough to handle different situations. If instead you
    make the core language powerful enough to write "print" as a function
    (which you can then put in the standard library for convenience), then
    people needing different related tools can make their own.

    These can all be handled in a language-definable function, and do not
    need special handling.

    No, they usually can't. Functions generally take a fixed number of parameters, and in a typed language, they are also usually a fixed type.

    Lots of languages have various methods for doing otherwise. Variadic functions, typeless parameters, function overloads, generic functions -
    these are all common in programming languages. They don't need
    built-ins. With greater freedom of use comes less compile-time checking
    - that's an inevitable tradeoff to some extent.


    Here is a task that prints an integer 'i', and its square root, followed
    by a newline, to the console, in several languages:

    Zig:-a-a std.debug.print("{} {}\n",.{i,@sqrt(@as(f64,@floatFromInt(i)))});

    C:-a-a-a-a printf("%d %f\n", i, sqrt(i));

    C++:-a-a std::cout << i << " " << sqrt(i) << std::endl;

    M:-a-a-a-a println i, sqrt i

    BASIC: 10 PRINT I, SQR(I)

    The first three all need prerequisites to make it work. The last two
    need nothing, not even variadic functions.

    Maybe it's a coincidence that both have Print and Sqrt as built-ins.

    BASIC is made to be simple to learn for beginners, and not for large,
    serious, long-term programs. And it's great for its task. But it is inflexible and not scalable.

    Oh, and modern C++ provides :

    import std;
    std::println("i = {}, reUi = {}", i, std::sqrt(i));

    With C11, I can write my own print/println macros so that I can write :

    println("i = ", i, ", reUi = ", sqrt(i));

    These are all type-safe, by the way.

    And with the C++ version, when you make "i" a complex number, it works
    the same. When you make a square matrix class and make "i" a matrix,
    you can write formatters (for the "cout" and "print/println/format"
    versions) for printing out your matrices. You can write a "sqrt"
    function for your matrices. (The C11 macros are less flexible - you
    need to know the types when the macros are defined.)


    Yes, BASIC - and your language - are simple for simple programs in
    specific use-cases and specific environments. And you will have added particular features as you needed them for your bigger programs. But
    they are not realistic for a wide audience and wide use-cases. There
    are good reasons that there are many different programs available.


    Other languages have their own problems in fitting those requirements
    to standard functions

    If you want something complex, it is complex.

    All you do by having it as a special built-in feature of the language
    is limited its usefulness, and mean that people have to re-invent it
    anyway.

    I understand your style of thinking - it's the way people thought
    about programming language forty-odd years ago.

    More like 50 years. But yes, when things were simple: see my examples
    above. So what the hell happened?

    The world moved on, and you didn't.

    When I was a teenager, I really enjoyed programming in BASIC, and wrote
    a lot of cool little programs on various computers. And there is no
    doubt that some things then were a lot simpler than writing the same
    thing in C. But the language and tools are totally unsuitable to work I
    do now. I don't use C for things that are hard to write in C - I use C
    for things that are best written in C. If another language is better
    for the task, I use that. ("Better" here includes being familiar with
    the language.)



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Tue Sep 29 09:54:30 2026
    From Newsgroup: comp.lang.c

    On 29/09/2026 02:24, Keith Thompson wrote:
    David Brown <david.brown@hesbynett.no> writes:
    [...]
    It is not a one-line function. Did you fail to read that bit of my
    post? My guess is that it was added to C (I have no idea when)

    hypot(), hypotf(), and hypotl() were added in C99, along with the type-generic macro hypot() in <tgmath.h>.

    [...]

    A C11 implementation might be :

    #define sin(x) \
    _Generic((x), \
    float : sinf, \
    double : sin, \
    long double : sinl, \
    float complex : csinf, \
    double complex : csin, \
    long double complex : csinl \
    )(x)

    That wouldn't be conforming. The sin() macro with an argument of an
    integer type has to work, converting the argument to double.

    I was simplifying somewhat, but you are right about the details. Real standard library implementations require more thought! As a first step,
    it should have a clause :

    default : sin \

    That will handle types that can be converted to double, but reject
    sin("foo"). I don't know if that would be enough, however - I have not
    tried to check everything.


    Handling that correctly and emitting sensible error messages for things
    like sin("foo") is difficult if the implementation uses _Generic,
    which is why some implementations use compiler "magic".

    Compiler magic can certainly lead to nicer error messages.


    (tcc uses _Generic for this -- and it appears to have a bug whereby sin("foo") is not diagnosed and produces a garbage result).

    [...]


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Tue Sep 29 11:11:28 2026
    From Newsgroup: comp.lang.c

    On 29/09/2026 08:03, Janis Papanagnou wrote:
    On 2026-09-28 16:12, David Brown wrote:
    On 28/09/2026 15:38, bart wrote:

    - Always available without needing those annoying #includes (and is
    -a-a it math.h or float.h? I can never remember).

    Other C programmers manage that without effort.

    I seem to recall that on his platform there's no man-pages.
    (Or that he, maybe, dislikes looking into the documentation?
    Sometime he gives that impression.)


    (Funny how shadowing or overriding is usually perceived as bad, until
    you want to shadow something like 'sin' then it's a must-have!)

    Since when is shadowing (or "overriding" in its various forms)
    "perceived as bad"? - I've always seen it as a useful feature.
    And never heard anyone complaining about it.

    It can be useful, it can also introduce subtle bugs if done inadvertently.

    For example you are using a global name inside a function but also
    happen to define a local of that name, so the global one is hidden.

    Of you forget to define a local variable and accidentally overwrite, or
    just use, the global version.

    You can see the same thing in file systems: in older Windows shells, it
    will first look up a file ABC in the current directory. In newer ones
    and on Linux, that is not allowed, you have to do ./ABC or .\ABC to
    explicitly refer to the local version.

    Why? The older Windows approach is convenient, but some obviously think
    it is bad.


    In decades I also
    don't recall that subtile (or obvious) errors had been reported
    because of that. (Are you, yet again, just making things up for
    the argument or have you any different observations from your
    personal coding practice?)

    You know, I'd been reading a series of posts by Lawrence D'Oliveiro, and assumed this was yet another.

    Until I got to the insults, which is uncharacteristic of him. And sure
    enough, I then noticed your name.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Tue Sep 29 12:54:15 2026
    From Newsgroup: comp.lang.c

    On 29/09/2026 08:45, David Brown wrote:
    On 28/09/2026 21:26, bart wrote:
    On 28/09/2026 17:49, David Brown wrote:

    Lots of programs have little or no use for "print", or they need
    something significantly different (showing messages in a dialog box,
    printing them to logs or serial ports, etc.

    So they /are/ using Print, which still has a variety of uses:


    No, they are not.

    They are doing /related/ tasks, but not the kind of thing you get from a "print" statement in BASIC.

    Well, BASIC has some other limitations (like no functions). But one of
    its purposes was for use from a terminal, and there PRINT is simple to use.

    (My SQRT example actually came from the first program I'd ever seen,
    which was in 1975. I was being shown around a college and I asked what
    some piece of computer equipment to do.

    My guide went to the nearest terminal (an ASR33) and typed in a program
    like this:

    10 FOR I=1, 20
    20 PRINT I, SQR(I)
    30 NEXT T

    He ran it and it printed, on the same paper, a table of square roots.
    (This BASIC printed numbers within a fixed-width field so it was nicely tabulated.))

    My claim is that all these tasks can be done with Print, and it is
    useful to have it as a built-in feature.

    If "print" is a fixed, special built-in feature of the language, then it
    is not flexible enough to handle different situations.

    Such as? Come on, give me a challenge!

    My first scripting language has Print with an option 'dev' like this:

    print #dev, items..

    'dev' could refer to the console, an open file, an LPT port, a COM port,
    a graphics window, an image, or a string.

    Yes, you can do all this a lot more awkwardly via functions, but so
    what? I can also do arithmetic via functions:

    a = ADD(b, MUL(c, c));

    This can also be a lot more powerful and flexible (eg. you have
    references to ADD or MUL and pass them to other functions), and they can implemented in libraries that people can override etc, but again so what?

    Most people prefer to have them somewhat less flexible and built-in so
    that they can do this:

    a = b + c * d;

    Here the language also takes care of overloads. I happen to think that
    Print is as fundamental as this.

    -a If instead you
    make the core language powerful enough to write "print" as a function
    (which you can then put in the standard library for convenience), then people needing different related tools can make their own.


    They can make their own anyway; I'm not stopping them. If stuck, they
    can always call 'printf' functions from a C library. This is a working
    program from my scripting language:

    a := i64.min
    b := "bart"

    println =a, =b

    printf("A=%lld, B=%s\n", a, b)

    Both print lines produce the same output. But the printf is more typing
    (at least I don't need a semicolon!), and it needs a precise format code
    which here I happened to know.

    But mine is 6 tokens while the printf version is 18 tokens (counting
    those inside the string), so why can't I prefer the compact version?

    Some people use Print a lot more than you!



    BASIC is made to be simple to learn for beginners, and not for large, serious, long-term programs.-a And it's great for its task.-a But it is inflexible and not scalable.

    Yes. But there are things to be learnt from it too. Can a language be as simple and clear as that, while also being more advanced?

    It seems many people think a language syntax has to be as abstruse as
    C++ in order to be taken seriously.

    Oh, and modern C++ provides :

    -a-a-a-aimport std;
    -a-a-a-astd::println("i = {}, reUi = {}", i, std::sqrt(i));

    So you agree that that "<<" business was an anomaly?

    With C11, I can write my own print/println macros so that I can write :

    -a-a-a-aprintln("i = ", i, ", reUi = ", sqrt(i));

    These are all type-safe, by the way.

    And with the C++ version, when you make "i" a complex number, it works
    the same.-a When you make a square matrix class and make "i" a matrix,
    you can write formatters (for the "cout" and "print/println/format" versions) for printing out your matrices.-a You can write a "sqrt"
    function for your matrices.-a (The C11 macros are less flexible - you
    need to know the types when the macros are defined.)

    OK, that's getting there. But how many advanced, complex (and inefficient-to-compile) language features are needed to arrive at this
    point?


    Yes, BASIC - and your language - are simple for simple programs in
    specific use-cases and specific environments.

    There are about 250 different Basics now - some will be OK used at scale
    (eg. the latest VB).

    While I can't see why my product, and my form of Print, can't scale either.

    I did ask above for a challenge. Don't forget it is possible to use
    other language features to create strings which are then submitted to
    Print! Or sometime they be output directly. The flexibility exists.
    More like 50 years. But yes, when things were simple: see my examples
    above. So what the hell happened?

    The world moved on, and you didn't.

    Well, I used to think that was a problem (and why I retired in 1999).
    Now I don't.

    I bet a lot of people are wishing the world hadn't moved on so much, and
    it's barely got going.

    I mean, it seems few people are going to doing much hands-on programming
    in the future so the question of whether Print is built-in or not will
    be moot.

    However, it is still relevant to me.


    When I was a teenager, I really enjoyed programming in BASIC, and wrote
    a lot of cool little programs on various computers.-a And there is no
    doubt that some things then were a lot simpler than writing the same
    thing in C.-a But the language and tools are totally unsuitable to work I
    do now.

    My experience was different: thrown in at the deep end into
    microprocessors, hardware and low-level work. My degree was CS not EE,
    but that job as test engineer from a small ad in the local paper was all
    I could find.

    So I used my background to create languages and tools to excel in my
    job, to apply them to the commercial software I later did, and which
    have now involved into what I have now.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@profesor.fir@gmail.com to comp.lang.c on Tue Sep 29 14:20:23 2026
    From Newsgroup: comp.lang.c

    Lawrence DrCOOliveiro pisze:
    On Tue, 29 Sep 2026 03:02:47 +0200, fir wrote:

    Lawrence DrCOOliveiro pisze:

    On Mon, 28 Sep 2026 12:42:31 +0200, fir wrote:

    its not breaking down, depend how you define breaking down for me
    for exampla sinf cosf or pow can be said are breaking don if thay
    count to much bits

    Your code breaks down because it cannot produce a result which is
    perfectly representable within the implementation range.

    LOL, im not sure if i understand this above sentence but for me code
    is broken if its too slow not when it present exact same graphics
    just faster

    DoesnrCOt correctness of the code figure into your thinking?


    what correctnes?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Tue Sep 29 14:36:34 2026
    From Newsgroup: comp.lang.c

    On 29/09/2026 07:38, Lawrence DrCOOliveiro wrote:
    On Mon, 28 Sep 2026 11:45:21 +0100, bart wrote:

    If C's obscure 'hypot' function does that job, then great.

    Nothing obscure about it. Every language with a decent maths library
    has it. To name but a few:
    <https://cppreference.com/cpp/numeric/math/hypot> <https://docs.python.org/3/library/math.html#math.hypot> <https://crates.io/crates/core_maths/0.1.1/code/src/lib.rs> <https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/lang/Math.java>

    Why? Because <https://en.wikipedia.org/wiki/IEEE_754>. WerCOve already discussed elsewhere why implementing it correctly is somewhat
    nontrivial, because the obvious na|>ve implementation is prone to be
    ... somewhat fragile.

    What exactly is incorrect about the naive method? That it stops working
    at a lower magnitude than hypot()?

    hypot() will also stop working at a high enough magnitude; so according
    to you, that is also incorrect?

    Both will work correctly according to their specs.

    If somebody wants the higher spec of hypotl for example (because their triangles have sides of 10**4000 units, although they might want a
    bigger universe first), then they can choose that routine.

    It might have however be slower than the simpler version.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Tue Sep 29 15:56:39 2026
    From Newsgroup: comp.lang.c

    On 29/09/2026 13:54, bart wrote:
    On 29/09/2026 08:45, David Brown wrote:
    On 28/09/2026 21:26, bart wrote:
    On 28/09/2026 17:49, David Brown wrote:

    Lots of programs have little or no use for "print", or they need
    something significantly different (showing messages in a dialog box,
    printing them to logs or serial ports, etc.

    So they /are/ using Print, which still has a variety of uses:


    No, they are not.

    They are doing /related/ tasks, but not the kind of thing you get from
    a "print" statement in BASIC.

    Well, BASIC has some other limitations (like no functions). But one of
    its purposes was for use from a terminal, and there PRINT is simple to use.

    That depends on the BASIC variant. In general, BASIC's were tuned to
    simple and specific environments. There's nothing wrong with that in
    itself, but they are not useful as wide-usage general purpose languages.

    My claim is that all these tasks can be done with Print, and it is
    useful to have it as a built-in feature.

    Built-in print is great for "Hello, world!" level programs, and a bit
    beyond that - but it quickly fails for larger needs.


    If "print" is a fixed, special built-in feature of the language, then
    it is not flexible enough to handle different situations.

    Such as? Come on, give me a challenge!

    I gave some already.

    Other things include formatted output to log files, formatting of
    different types (not just built-in ones), saving logs in eeprom, using different languages for the fixed parts of the strings. Basically,
    anything that the toolchain writer and/or language designer didn't think
    of in the first place.


    My first scripting language has Print with an option 'dev' like this:

    -a print #dev, items..

    'dev' could refer to the console, an open file, an LPT port, a COM port,
    a graphics window, an image, or a string.

    That's only the things /you/ thought about at the time. It doesn't
    cover what other people think of later. And it means the language is
    burdened with this stuff even if it is not relevant to the user.
    (That's less of an issue with a scripting language than a compiled
    language.)



    Yes, you can do all this a lot more awkwardly via functions, but so
    what? I can also do arithmetic via functions:

    -a-a a = ADD(b, MUL(c, c));

    This can also be a lot more powerful and flexible (eg. you have
    references to ADD or MUL and pass them to other functions), and they can implemented in libraries that people can override etc, but again so what?

    Most people prefer to have them somewhat less flexible and built-in so
    that they can do this:

    -a a = b + c * d;


    For basic arithmetic, it's easy to specify the main operations. There
    is a bit of decision making for things like power operators, but it's
    mostly all there. Printing is not like that.

    And more advanced languages let you override operators for different
    types, precisely so that you don't have to use prefix function notation
    for your application or library types.

    Here the language also takes care of overloads. I happen to think that
    Print is as fundamental as this.


    In your limited bubble, that's maybe fine. I'm not saying it is a bad
    choice for /your/ language - it's a bad choice for most scalable general-purpose languages.

    -a If instead you make the core language powerful enough to write
    "print" as a function (which you can then put in the standard library
    for convenience), then people needing different related tools can make
    their own.



    Oh, and modern C++ provides :

    -a-a-a-a-aimport std;
    -a-a-a-a-astd::println("i = {}, reUi = {}", i, std::sqrt(i));

    So you agree that that "<<" business was an anomaly?

    I did not say anything of the sort. I said that modern C++ provides a different way of doing this - with different pros and cons.

    There are things I dislike about iostreams in C++, but it is a solution
    that can be very convenient for some uses. The same applies to every
    "print" system I have ever seen. That's why it is so important for
    serious languages to make them library features.

    The C++ language features required to make the std::println() system
    work well did not exist when the "cout << " system was developed. The
    effort demanded of compilers would have been too much at that time.
    Computers are faster and have more resources, so a new more powerful
    solution can be made that is type-safe and generates efficient object
    code. (The effort needed by compilers is irrelevant in comparison.)


    With C11, I can write my own print/println macros so that I can write :

    -a-a-a-a-aprintln("i = ", i, ", reUi = ", sqrt(i));

    These are all type-safe, by the way.

    And with the C++ version, when you make "i" a complex number, it works
    the same.-a When you make a square matrix class and make "i" a matrix,
    you can write formatters (for the "cout" and "print/println/format"
    versions) for printing out your matrices.-a You can write a "sqrt"
    function for your matrices.-a (The C11 macros are less flexible - you
    need to know the types when the macros are defined.)

    OK, that's getting there. But how many advanced, complex (and inefficient-to-compile) language features are needed to arrive at this point?

    It needs _Generic, and variadic macros.



    Yes, BASIC - and your language - are simple for simple programs in
    specific use-cases and specific environments.

    There are about 250 different Basics now - some will be OK used at scale (eg. the latest VB).

    VB is a zombie - no matter how hard people try, it is impossible to kill
    it off entirely. In VB, printing was not done with a built-in statement
    - you used function calls (or methods on labels, dialog boxes, etc.).

    The world moved on, and you didn't.

    Well, I used to think that was a problem (and why I retired in 1999).
    Now I don't.

    I bet a lot of people are wishing the world hadn't moved on so much, and it's barely got going.

    Maybe. Everyone has things that they miss from "the good old days".
    Usually their memories are clouded and biased, but there will be some
    truth in it.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Tue Sep 29 16:01:54 2026
    From Newsgroup: comp.lang.c

    On 2026-09-29 09:45, David Brown wrote:
    On 28/09/2026 21:26, bart wrote:
    On 28/09/2026 17:49, David Brown wrote:
    On 28/09/2026 17:52, bart wrote:

    Yes, I know, most languages prefer to have things in libraries
    rather than in the core.

    So perhaps it's a good idea?

    IS it a good idea? Or is it just what is commonly done and people go
    along with it?

    Putting functions in standard libraries is commonly done because it is a good idea.

    Very occasionally, in some field of thought, someone will come along
    with a crazy idea that is different from the way everyone else does
    things, and their new way is revolutionary and changes the field
    forever.-a [...]

    Sometimes it's not even a "crazy idea" or "revolutionary"; I recall
    we "replaced" malloc() and free() by own versions to keep track of
    memory allocation, and to find unused but unreleased memory chunks.
    (It's not printf() but these are also central functions of "C".)
    That was about 35 years ago - meanwhile there's many tools existing.

    [...]

    No, they usually can't. Functions generally take a fixed number of
    parameters, and in a typed language, they are also usually a fixed type.

    What folly are you emitting again! - printf/scanf, or more general
    "varargs" in "C", write/ln in Pascal, Awk where you can pass what
    you like (sort of), the Unix shell, languages that have per design
    no fixed number of arguments, languages that use clever mechanisms
    to pass many arguments in the form a single argument sequence, and
    whatnot. And quite some of those have their mechanisms implemented
    even type-safe.


    Lots of languages have various methods for doing otherwise.-a Variadic functions, typeless parameters, function overloads, generic functions - these are all common in programming languages.-a They don't need built- ins.-a With greater freedom of use comes less compile-time checking -
    that's an inevitable tradeoff to some extent.

    [...]

    Yes, BASIC - and your language - are simple for simple programs ]...]

    When I was a teenager, I really enjoyed programming in BASIC, and wrote
    a lot of cool little programs on various computers.-a And there is no
    doubt that some things then were a lot simpler than writing the same
    thing in C.-a [...]

    Interesting. - As teenager I also wrote lots of fancy BASIC programs.
    But as soon as Pascal was available that was a lot more fun (for me),
    and a bit step forward! With "C" things degraded, though. (Again, for
    me.)

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Tue Sep 29 15:02:43 2026
    From Newsgroup: comp.lang.c

    On 29/09/2026 08:08, Lawrence DrCOOliveiro wrote:
    On Mon, 28 Sep 2026 14:38:09 +0100, bart wrote:

    On 28/09/2026 12:56, David Brown wrote:

    "hypot" - short for "hypotenuse" but easier to spell - is not
    obscure. It is a common name and part of the IEEE 754 standard.-a It
    makes a lot of sense for a language that is often used with code
    that requires conformance to that standard, to have support for the
    standard's required and recommended functions in its standard
    library.-a As Lawrence showed, proper implementations of such
    functions is not just a matter of copying the pure mathematical
    formula.

    He showed a way to avoid overflowing (with inputs above 10**19) if
    you can't be bothered to use a more appropriate type.

    I knew somewhat would try to make this claim, sooner or later. So
    hererCOs a long-double version -- I donrCOt think GCC supports any floating-point formats with greater range or precision than this!

    /*
    Comparison of the na|>ve calculation of a triangle
    hypotenuse with the standard-library hypot(3) function.
    */

    #include <math.h>
    #include <values.h>
    #include <stdio.h>

    static long double len2(long double x,long double y) { return sqrtl(x*x+y*y);}

    static void compare_for
    (
    long double x
    )
    {
    fprintf
    (
    stdout,
    "for %.7Le: len2 = %.7Le, hypot = %.7Le\n",
    x, len2(x, x), hypotl(x, x)
    );
    } /*compare_for*/

    int main(void)
    {
    compare_for(LDBL_MAX / 2.0);
    compare_for(2.0 / LDBL_MAX);
    return
    0;
    } /*main*/

    Output:

    ldo@theon:c_try> ./naive_hypot_long_double
    for 5.9486575e+4931: len2 = inf, hypot = 8.4126721e+4931
    for 1.6810516e-4932: len2 = 0.0000000e+00, hypot = 2.3773659e-4932

    So the library routine is still capable of producing meaningful results, while the na|>ve implementation still breaks down.

    Any more nitpicks?

    Yes: you're being incredibly pedantic and picky for no reason other than
    to be argumentative and superior.

    These big numbers are ridiculous. If you want to play this game, then
    I've just got my bignum library to work out the hypotenuse given these
    two sides:

    A = 3e1'000'000'000'000'000'000
    B = 4e1'000'000'000'000'000'000

    (The is, 3 and 4 each followed by a million million million zeros.)

    So tell me again what is the upper limit when using hypotl()?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.c on Tue Sep 29 14:38:05 2026
    From Newsgroup: comp.lang.c

    bart <bc@freeuk.com> writes:
    On 29/09/2026 08:03, Janis Papanagnou wrote:
    On 2026-09-28 16:12, David Brown wrote:

    You can see the same thing in file systems: in older Windows shells, it
    will first look up a file ABC in the current directory. In newer ones
    and on Linux, that is not allowed, you have to do ./ABC or .\ABC to >explicitly refer to the local version.

    You are referring, of course, to the algorithms used to locate
    the executable corresponding to a command that is not built-in
    to the shell.

    Your characterization of Unix-like systems is incorrect. If you
    specify '.' in the $PATH environment variable, the shell will
    happily look in the current working directory when searching
    for an executable.

    I suspect the same might even be true for DOS.

    Given that it is a security issue to include '.'
    in the PATH, it is not there by default on most
    distributions.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.c on Tue Sep 29 14:43:12 2026
    From Newsgroup: comp.lang.c

    bart <bc@freeuk.com> writes:
    On 29/09/2026 08:08, Lawrence DrCOOliveiro wrote:
    On Mon, 28 Sep 2026 14:38:09 +0100, bart wrote:

    On 28/09/2026 12:56, David Brown wrote:

    "hypot" - short for "hypotenuse" but easier to spell - is not
    obscure. It is a common name and part of the IEEE 754 standard.-a It
    makes a lot of sense for a language that is often used with code
    that requires conformance to that standard, to have support for the
    standard's required and recommended functions in its standard
    library.-a As Lawrence showed, proper implementations of such
    functions is not just a matter of copying the pure mathematical
    formula.

    He showed a way to avoid overflowing (with inputs above 10**19) if
    you can't be bothered to use a more appropriate type.

    I knew somewhat would try to make this claim, sooner or later. So
    hererCOs a long-double version -- I donrCOt think GCC supports any
    floating-point formats with greater range or precision than this!

    /*
    Comparison of the na|>ve calculation of a triangle
    hypotenuse with the standard-library hypot(3) function.
    */

    #include <math.h>
    #include <values.h>
    #include <stdio.h>

    static long double len2(long double x,long double y) { return sqrtl(x*x+y*y);}

    static void compare_for
    (
    long double x
    )
    {
    fprintf
    (
    stdout,
    "for %.7Le: len2 = %.7Le, hypot = %.7Le\n",
    x, len2(x, x), hypotl(x, x)
    );
    } /*compare_for*/

    int main(void)
    {
    compare_for(LDBL_MAX / 2.0);
    compare_for(2.0 / LDBL_MAX);
    return
    0;
    } /*main*/

    Output:

    ldo@theon:c_try> ./naive_hypot_long_double
    for 5.9486575e+4931: len2 = inf, hypot = 8.4126721e+4931
    for 1.6810516e-4932: len2 = 0.0000000e+00, hypot = 2.3773659e-4932

    So the library routine is still capable of producing meaningful results,
    while the na|>ve implementation still breaks down.

    Any more nitpicks?

    Yes: you're being incredibly pedantic and picky for no reason other than
    to be argumentative and superior.

    These big numbers are ridiculous. If you want to play this game, then
    I've just got my bignum library to work out the hypotenuse given these
    two sides:

    A = 3e1'000'000'000'000'000'000
    B = 4e1'000'000'000'000'000'000

    (The is, 3 and 4 each followed by a million million million zeros.)

    The nice thing about computing the hypotenuse, is that you
    can simply scale the values of A&B down before computing C
    to get the correct answer.

    I believe many implementations already do that internally
    to avoid over/underflow cases.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Tue Sep 29 16:07:40 2026
    From Newsgroup: comp.lang.c

    On 29/09/2026 15:43, Scott Lurndal wrote:
    bart <bc@freeuk.com> writes:
    On 29/09/2026 08:08, Lawrence DrCOOliveiro wrote:
    On Mon, 28 Sep 2026 14:38:09 +0100, bart wrote:

    On 28/09/2026 12:56, David Brown wrote:

    "hypot" - short for "hypotenuse" but easier to spell - is not
    obscure. It is a common name and part of the IEEE 754 standard.-a It >>>>> makes a lot of sense for a language that is often used with code
    that requires conformance to that standard, to have support for the
    standard's required and recommended functions in its standard
    library.-a As Lawrence showed, proper implementations of such
    functions is not just a matter of copying the pure mathematical
    formula.

    He showed a way to avoid overflowing (with inputs above 10**19) if
    you can't be bothered to use a more appropriate type.

    I knew somewhat would try to make this claim, sooner or later. So
    hererCOs a long-double version -- I donrCOt think GCC supports any
    floating-point formats with greater range or precision than this!

    /*
    Comparison of the na|>ve calculation of a triangle
    hypotenuse with the standard-library hypot(3) function.
    */

    #include <math.h>
    #include <values.h>
    #include <stdio.h>

    static long double len2(long double x,long double y) { return sqrtl(x*x+y*y);}

    static void compare_for
    (
    long double x
    )
    {
    fprintf
    (
    stdout,
    "for %.7Le: len2 = %.7Le, hypot = %.7Le\n",
    x, len2(x, x), hypotl(x, x)
    );
    } /*compare_for*/

    int main(void)
    {
    compare_for(LDBL_MAX / 2.0);
    compare_for(2.0 / LDBL_MAX);
    return
    0;
    } /*main*/

    Output:

    ldo@theon:c_try> ./naive_hypot_long_double
    for 5.9486575e+4931: len2 = inf, hypot = 8.4126721e+4931
    for 1.6810516e-4932: len2 = 0.0000000e+00, hypot = 2.3773659e-4932 >>>
    So the library routine is still capable of producing meaningful results, >>> while the na|>ve implementation still breaks down.

    Any more nitpicks?

    Yes: you're being incredibly pedantic and picky for no reason other than
    to be argumentative and superior.

    These big numbers are ridiculous. If you want to play this game, then
    I've just got my bignum library to work out the hypotenuse given these
    two sides:

    A = 3e1'000'000'000'000'000'000
    B = 4e1'000'000'000'000'000'000

    (The is, 3 and 4 each followed by a million million million zeros.)

    The nice thing about computing the hypotenuse, is that you
    can simply scale the values of A&B down before computing C
    to get the correct answer.

    I believe many implementations already do that internally
    to avoid over/underflow cases.

    You can probably do that in any number of examples, if you think might
    you might run out of range, even though f64 is generous.

    So what's special about the sqrt(x*x + y*y) expression that defines how
    hypot works, compared with a million others across codebases?

    I can understand if the types involved are f8 or f16, but usually even
    f32 is not a problem.

    Note that my bignum example did it without scaling,

    It's also worth noting that if using the x87, it calculates internally
    using higher precision and range than 64 bits (I think 15-bit exponents
    rather than 11).

    So it should be able to do a naive hypot() that takes 64-bit floats up
    to almost the full range, without overflow and without any tricks.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Paul@nospam@needed.invalid to comp.lang.c on Tue Sep 29 12:39:41 2026
    From Newsgroup: comp.lang.c

    On Tue, 9/29/2026 8:20 AM, fir wrote:
    Lawrence DrCOOliveiro pisze:
    On Tue, 29 Sep 2026 03:02:47 +0200, fir wrote:

    Lawrence DrCOOliveiro pisze:

    On Mon, 28 Sep 2026 12:42:31 +0200, fir wrote:

    its not breaking down, depend how you define breaking down for me
    for exampla sinf cosf or pow can be said are breaking don if thay
    count to much bits

    Your code breaks down because it cannot produce a result which is
    perfectly representable within the implementation range.

    LOL, im not sure if i understand this above sentence but for me code
    is broken if its too slow not when it present exact same graphics
    just faster

    DoesnrCOt correctness of the code figure into your thinking?


    what correctnes?

    When you write a function like that, you should have
    a comment at the top of the function, defining the
    valid domain and range for it. It's OK for a function
    to be "approximate", as long as the details of
    "how bad is my function", are noted.

    In this example it says:

    https://randomascii.wordpress.com/2014/10/09/intel-underestimates-error-bounds-by-1-3-quintillion/

    "Sin() is trivial (for almost half of input values)

    For small enough doubles, the best answer for sin(x) is x.

    That is, for numbers smaller than about 1.49e-8, the closest double to the sine of x
    is actually x itself. I learned this from the glibc source code for sin().
    "

    Taking advantage of that kind of observation, means some calls
    to sin() are fast, some calls to sin() via range-reduction, are slow.

    And range-reduction must be done with a bit of care, or the error
    could be relatively large.

    Paul
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Tue Sep 29 18:15:44 2026
    From Newsgroup: comp.lang.c

    On 29/09/2026 14:56, David Brown wrote:
    On 29/09/2026 13:54, bart wrote:
    My claim is that all these tasks can be done with Print, and it is
    useful to have it as a built-in feature.

    Built-in print is great for "Hello, world!" level programs, and a bit
    beyond that - but it quickly fails for larger needs.

    That is nonsense.

    Such as? Come on, give me a challenge!

    I gave some already.

    Other things include formatted output to log files, formatting of
    different types (not just built-in ones), saving logs in eeprom, using different languages for the fixed parts of the strings.-a Basically, anything that the toolchain writer and/or language designer didn't think
    of in the first place.
    And yet some sort of friendlier Print feature is generally provided by a language, on top of a set of I/O routines.

    For example Lua has print() as well as io.write. I think Python also has
    'io', and 'sys', and 'os'.

    So they recognise that providing the simpler Print feature as well adds something.

    So do I! I just go further and make it built-in to make even more
    convenient and with nicer syntax.

    formatting of different types (not just built-in ones)

    This is a separate requirement. If you mean being able to use standard
    Print on a user-type so that it invokes a user-defined stringify
    routine, then C has some trouble here too.

    (I have it in my dynamic language, achieved by overloading the 'tostr' operator that Print usually applies implicitly. Print is built-in.)

    , using
    different languages for the fixed parts of the strings.

    This is that weird ordering thing of printf? You do know you can apply
    other language features to expressions before submitting the results to
    Print?

    You can also not use Print in this case. I use Print for convenience and during development.

    My first scripting language has Print with an option 'dev' like this:

    -a-a print #dev, items..

    'dev' could refer to the console, an open file, an LPT port, a COM
    port, a graphics window, an image, or a string.

    That's only the things /you/ thought about at the time.-a It doesn't
    cover what other people think of later.

    What other destinations can you think of? Bear in mind that in Linux,
    most such things seems to be part of the file system, and that is
    already covered.

    Here the language also takes care of overloads. I happen to think that
    Print is as fundamental as this.


    In your limited bubble, that's maybe fine.-a I'm not saying it is a bad choice for /your/ language - it's a bad choice for most scalable general-purpose languages.

    You do know you can have both built-in Print /and/ an I/O library? This
    point was made above.

    And with the C++ version, when you make "i" a complex number, it

    OK, that's getting there. But how many advanced, complex (and
    inefficient-to-compile) language features are needed to arrive at this
    point?

    It needs _Generic, and variadic macros.

    I was thinking of C++. But _Generic and variadic macros in C (add them
    to variadic functions) I would class as a hack.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Tue Sep 29 20:24:10 2026
    From Newsgroup: comp.lang.c

    On 29/09/2026 19:15, bart wrote:
    On 29/09/2026 14:56, David Brown wrote:
    On 29/09/2026 13:54, bart wrote:
    My claim is that all these tasks can be done with Print, and it is
    useful to have it as a built-in feature.

    Built-in print is great for "Hello, world!" level programs, and a bit
    beyond that - but it quickly fails for larger needs.

    That is nonsense.

    Such as? Come on, give me a challenge!

    I gave some already.

    Other things include formatted output to log files, formatting of
    different types (not just built-in ones), saving logs in eeprom, using
    different languages for the fixed parts of the strings.-a Basically,
    anything that the toolchain writer and/or language designer didn't
    think of in the first place.
    And yet some sort of friendlier Print feature is generally provided by a language, on top of a set of I/O routines.

    For example Lua has print() as well as io.write. I think Python also has 'io', and 'sys', and 'os'.

    So they recognise that providing the simpler Print feature as well adds something.

    So do I! I just go further and make it built-in to make even more
    convenient and with nicer syntax.


    There is /nothing/ wrong with making a simple "print" function.

    There is a lot wrong with making it a special language feature, instead
    of a normal function (or other language construct - object, template,
    generic, whatever) that is defined in the standard library, using the
    language itself.

    If you can't make a suitable "print" facility that way, your language is
    weak and limited. It might be okay for some purposes, but not for
    general usage. (And if you /can/ make it part of the standard library,
    you /should/ make it part of the standard library - even if your
    language then imports that library by default.)


    What other destinations can you think of? Bear in mind that in Linux,
    most such things seems to be part of the file system, and that is
    already covered.


    Not everything you might want to do in Linux is part of the file system
    - far from it. And not all programs run on Windows or Linux.

    /I/ am not the one implicitly claiming to know all possible
    destinations, uses or combinations so that it's fine to nail it into a language special feature.


    And with the C++ version, when you make "i" a complex number, it

    OK, that's getting there. But how many advanced, complex (and
    inefficient-to-compile) language features are needed to arrive at
    this point?

    It needs _Generic, and variadic macros.

    I was thinking of C++. But _Generic and variadic macros in C (add them
    to variadic functions) I would class as a hack.


    You class everything that is not part of your beloved language as a
    "hack". You'll forgive me for not taking your opinion or
    classifications seriously.

    For C++, basically all that was needed for "cout << x" was overloaded operators for user-defined (or library-defined, it's the same thing) types.

    For the newer "std::print" and "std::format" functions, more powerful compile-time evaluation was needed. Guaranteed compile-time of
    functions is a useful feature of newer C++, as it gives more efficient
    object code while letting you be flexible in your source code without
    having to pre-calculate things. The "format" library combines this with variadic templates and functions to get fully static type-checking of
    the formats. The implementation of these things is complicated - no
    question about it. But it uses features that are already in the
    language and useful for a great many purposes - it did not need special language features added just to be able to write "std::format" or "std::print".



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.c on Tue Sep 29 19:41:42 2026
    From Newsgroup: comp.lang.c

    David Brown <david.brown@hesbynett.no> writes:
    On 29/09/2026 19:15, bart wrote:

    <snip>

    There is /nothing/ wrong with making a simple "print" function.

    There is a lot wrong with making it a special language feature, instead
    of a normal function (or other language construct - object, template, >generic, whatever) that is defined in the standard library, using the >language itself.

    If you can't make a suitable "print" facility that way, your language is >weak and limited. It might be okay for some purposes, but not for
    general usage. (And if you /can/ make it part of the standard library,
    you /should/ make it part of the standard library - even if your
    language then imports that library by default.)

    Agreed.


    What other destinations can you think of? Bear in mind that in Linux,
    most such things seems to be part of the file system, and that is
    already covered.


    Not everything you might want to do in Linux is part of the file system
    - far from it.

    Some examples often used in server code:

    - The host log framework (e.g. syslog) is a common destination
    - A network TCP/UDP port
    - A custom multiplexer to send the output to multiple destinations

    There is a lot to be said for the terseness of *printf formatting,
    particularly with compilers that check the type correctness of the printf varargs list.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From cross@cross@spitfire.i.gajendra.net (Dan Cross) to comp.lang.c on Tue Sep 29 21:37:50 2026
    From Newsgroup: comp.lang.c

    In article <WvUuS.292$M0U7.280@fx10.iad>,
    Scott Lurndal <slp53@pacbell.net> wrote:
    David Brown <david.brown@hesbynett.no> writes:
    On 29/09/2026 19:15, bart wrote:

    <snip>

    There is /nothing/ wrong with making a simple "print" function.

    There is a lot wrong with making it a special language feature, instead
    of a normal function (or other language construct - object, template, >>generic, whatever) that is defined in the standard library, using the >>language itself.

    If you can't make a suitable "print" facility that way, your language is >>weak and limited. It might be okay for some purposes, but not for
    general usage. (And if you /can/ make it part of the standard library, >>you /should/ make it part of the standard library - even if your
    language then imports that library by default.)

    Agreed.


    What other destinations can you think of? Bear in mind that in Linux,
    most such things seems to be part of the file system, and that is
    already covered.


    Not everything you might want to do in Linux is part of the file system
    - far from it.

    Some examples often used in server code:

    - The host log framework (e.g. syslog) is a common destination
    - A network TCP/UDP port
    - A custom multiplexer to send the output to multiple destinations

    To be fair to Bart, I think he was implying that L/Unix systems
    try to use a uniform interface for IO, modeling endpoints as if
    they were files, associating those endpoints with small integers
    that resemble file descriptors, and using those for indirection
    between the system calls that effect actual IO and a userspace
    program.

    So the file descriptors returned by `open` behave an awful lot
    like the pair allocated to a pipe or socketpair, which bear a
    striking resemblence to a socket descriptor, and so on; all can
    be the target of a `write`, or `read`, or `close`. Of course
    there are some differences as those are different kinds of
    objects after all. What does `lseek` mean on a pipe? It
    doesn't; it's a category error, and POSIX defines it thusly.

    But in terms of general shape of the interface, the analogy is
    not bad, though it's not the "filesystem" that does this, but
    rather, the file-related API.

    Of course, those _system calls_ don't do formatting of their own
    (modulo a tty layer that might do, say, line end conversions or
    things like that).

    There is a lot to be said for the terseness of *printf formatting, >particularly with compilers that check the type correctness of the printf >varargs list.

    I'd say the real winning example is `snprintf`, where one can
    format directly into a character array. It is difficult to
    understate the utility this; but if `print` were built into the
    language, you'd lose it, unless you also had a `sprint` builtin.

    - Dan C.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Tue Sep 29 22:49:02 2026
    From Newsgroup: comp.lang.c

    On Tue, 29 Sep 2026 14:36:34 +0100, bart wrote:

    On 29/09/2026 07:38, Lawrence DrCOOliveiro wrote:

    Why? Because <https://en.wikipedia.org/wiki/IEEE_754>. WerCOve
    already discussed elsewhere why implementing it correctly is
    somewhat nontrivial, because the obvious na|>ve implementation is
    prone to be ... somewhat fragile.

    What exactly is incorrect about the naive method? That it stops
    working at a lower magnitude than hypot()?

    hypot() will also stop working at a high enough magnitude; so
    according to you, that is also incorrect?

    Feel free to demonstrate the point at which the library function stops
    working.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Tue Sep 29 22:50:57 2026
    From Newsgroup: comp.lang.c

    On Tue, 29 Sep 2026 14:20:23 +0200, fir wrote:

    Lawrence DrCOOliveiro pisze:

    DoesnrCOt correctness of the code figure into your thinking?

    what correctnes?

    We have here a standard library function, already implemented, that
    provides better-quality results than your somewhat simplistic attempt.
    Why should we bother with your code at all?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Tue Sep 29 23:59:58 2026
    From Newsgroup: comp.lang.c

    On 29/09/2026 23:49, Lawrence DrCOOliveiro wrote:
    On Tue, 29 Sep 2026 14:36:34 +0100, bart wrote:

    On 29/09/2026 07:38, Lawrence DrCOOliveiro wrote:

    Why? Because <https://en.wikipedia.org/wiki/IEEE_754>. WerCOve
    already discussed elsewhere why implementing it correctly is
    somewhat nontrivial, because the obvious na|>ve implementation is
    prone to be ... somewhat fragile.

    What exactly is incorrect about the naive method? That it stops
    working at a lower magnitude than hypot()?

    hypot() will also stop working at a high enough magnitude; so
    according to you, that is also incorrect?

    Feel free to demonstrate the point at which the library function stops working.


    Take your example using hypotl() and remove the '/ 2.0'. (Then the
    answer needs to be about 1.4142 * LDBL_MAX.)

    Or maybe your triangle has a, b sides bigger than LDBL_MAX, or an
    earlier calculation has already overflowed.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Wed Sep 30 00:13:23 2026
    From Newsgroup: comp.lang.c

    On 29/09/2026 23:58, Lawrence DrCOOliveiro wrote:
    On Tue, 29 Sep 2026 15:02:43 +0100, bart wrote:

    On 29/09/2026 08:08, Lawrence DrCOOliveiro wrote:

    So the library routine is still capable of producing meaningful
    results, while the na|>ve implementation still breaks down.

    Any more nitpicks?

    Yes: you're being incredibly pedantic and picky for no reason other
    than to be argumentative and superior.

    YourCOre the one failing to appreciate the point, that it takes smarts
    to design proper numeric algorithms that work within the practical *efficient* limits of computer arithmetic.

    OK, so give me a 'smart' square(x) routine where x can go all the way to
    the MAX value.

    These big numbers are ridiculous. If you want to play this game,
    then I've just got my bignum library ...

    So those numbers are rCLridiculousrCY, yet your only way to counter
    them is to be more rCLridiculousrCY?

    Yes; they're all ridiculous. You're criticising some line-length routine because it goes wrong when deltas reach 10**19 (f32), or some 10**153
    (f64) or 10**4000 or whatever (f80).

    Mine I think will go wrong at 10**5000000000000000000 or something.

    But IT DOESN'T MATTER.

    You're also looking at this wrong way: the author of len2() (ie. the
    'naive' version) wrote it with his applications in mind, where its spec
    was perfectly adequate for the job.

    The API list was a suggestion for some functions to be standardised,
    rather than be actual official implementations.

    As the author of a library function, you don't know to what applications
    it will be used for, so you don't make assumptions.

    Also you're not going to get paid much for one line of code so you might
    as well go to town.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Tue Sep 29 16:48:31 2026
    From Newsgroup: comp.lang.c

    On 9/29/2026 12:54 AM, David Brown wrote:
    [...]

    sin("foo"). Hopefully the compiler can say at least wtf? Are you sure?

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Tue Sep 29 16:50:23 2026
    From Newsgroup: comp.lang.c

    On 9/28/2026 8:40 AM, bart wrote:
    On 28/09/2026 16:15, James Kuyper wrote:
    On 28/09/2026 12:45, bart wrote:
    On 28/09/2026 09:25, David Brown wrote:
    It also has a "hypot" function that returns, approximately,
    sqrt(x*x +
    y*y).
    So why was hypot() ever added? Somebody thought it was a good
    idea at
    one time to add a such a one-line function?
    It was part of the major expansion to the <math.h> library that occurred
    in C99. It was added because of the "without undue overflow or
    underflow." requirement. Achieving that result makes it a bit more
    complicated than just a one-line function. Also, even most people who
    are well aware of that problem are unaware of how best to avoid it. See
    <https://en.wikipedia.org/wiki/Pythagorean_addition#Calculation_order>
    for more details.

    I think most will be vaguely aware of such problems, but usually they
    don't matter because they only happen with unlikely, extreme inputs.

    One simple way around in this case, is to use 64-bit floats for the calculation, even if the inputs are 32-bits.

    That might kick the can down the road enough that overflows will
    virtually never occur (eg. it might need inputs over 10**150, and that I think is impossible if inputs were promoted from 32 bits).

    I'm less familiar with underflows, ie. values smaller than around
    10e-308, but I think the same applies.

    The technique demonstrated in LD'O's post I think buys you one more bit
    of exponent range (although the article you linked to seems to suggest
    you can go beyond that with extra scaling).

    When such things used to be important to me, I tried to avoid doing the square-root part anyway, for example I would compare one set of x*x +
    y*y with another. In that case it is necessary to express the full magnitude.

    If the values represent length, then another approach would be a choice
    of units. I liked using mm, but if expressed in metres, then I think
    that's another 10 extra bits of binary exponent range, unless the issue
    is underflow, then it might make it worse!

    In any case, it was NEVER a problem (well, until someone zoomed in
    enough within my CAD product that they hit the limitations of the
    floating point representation. Things would get jerky).


    ponder on atan vs atan2?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Tue Sep 29 16:51:34 2026
    From Newsgroup: comp.lang.c

    On 9/29/2026 3:59 PM, bart wrote:
    On 29/09/2026 23:49, Lawrence DrCOOliveiro wrote:
    On Tue, 29 Sep 2026 14:36:34 +0100, bart wrote:

    On 29/09/2026 07:38, Lawrence DrCOOliveiro wrote:

    Why? Because <https://en.wikipedia.org/wiki/IEEE_754>. WerCOve
    already discussed elsewhere why implementing it correctly is
    somewhat nontrivial, because the obvious na|>ve implementation is
    prone to be ... somewhat fragile.

    What exactly is incorrect about the naive method? That it stops
    working at a lower magnitude than hypot()?

    hypot() will also stop working at a high enough magnitude; so
    according to you, that is also incorrect?

    Feel free to demonstrate the point at which the library function stops
    working.


    Take your example using hypotl() and remove the '/ 2.0'. (Then the
    answer needs to be about 1.4142 * LDBL_MAX.)

    Or maybe your triangle has a, b sides bigger than LDBL_MAX, or an
    earlier calculation has already overflowed.

    Well, we have bounds and ways to use properly use functions, right?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Wed Sep 30 01:19:21 2026
    From Newsgroup: comp.lang.c

    On 29/09/2026 19:24, David Brown wrote:
    On 29/09/2026 19:15, bart wrote:
    On 29/09/2026 14:56, David Brown wrote:
    On 29/09/2026 13:54, bart wrote:
    My claim is that all these tasks can be done with Print, and it is
    useful to have it as a built-in feature.

    Built-in print is great for "Hello, world!" level programs, and a bit
    beyond that - but it quickly fails for larger needs.

    That is nonsense.

    Such as? Come on, give me a challenge!

    I gave some already.

    Other things include formatted output to log files, formatting of
    different types (not just built-in ones), saving logs in eeprom,
    using different languages for the fixed parts of the strings.
    Basically, anything that the toolchain writer and/or language
    designer didn't think of in the first place.
    And yet some sort of friendlier Print feature is generally provided by
    a language, on top of a set of I/O routines.

    For example Lua has print() as well as io.write. I think Python also
    has 'io', and 'sys', and 'os'.

    So they recognise that providing the simpler Print feature as well
    adds something.

    So do I! I just go further and make it built-in to make even more
    convenient and with nicer syntax.


    There is /nothing/ wrong with making a simple "print" function.

    There is a lot wrong with making it a special language feature, instead
    of a normal function (or other language construct - object, template, generic, whatever) that is defined in the standard library, using the language itself.

    If you can't make a suitable "print" facility that way, your language is weak and limited.

    That's your opinion. You like such features, you like DIY languages, and
    you like lots of moving pieces. In general, you like complexity.

    I don't like language-building features as they make for a more
    complicated, harder-to-understand and slower-to-compile language. I also
    like things self-contained and tidy.

    My Print works. As for any special tasks, they will be no different from
    any other; you just write some code like for anything else.


    -a It might be okay for some purposes, but not for
    general usage.-a (And if you /can/ make it part of the standard library,
    you /should/ make it part of the standard library - even if your
    language then imports that library by default.)

    Nothing stops anyone writing their own library of print-related
    routines, even in my language.

    But if they also want decent ergonomics, then they will need advanced features; they will need to look elsewhere.

    What other destinations can you think of? Bear in mind that in Linux,
    most such things seems to be part of the file system, and that is
    already covered.


    Not everything you might want to do in Linux is part of the file system
    - far from it.-a And not all programs run on Windows or Linux.

    /I/ am not the one implicitly claiming to know all possible
    destinations, uses or combinations so that it's fine to nail it into a language special feature.

    But you seem certain that a Print feature like that can't work! I think
    after some decades of use, I would have noticed.


    You class everything that is not part of your beloved language as a
    "hack".

    In the case of C, then I've seen enough system header files to
    justifiably call them hacks. In fact I'll go further and call them ugly
    hacks. That's how C seems to work.

    -a You'll forgive me for not taking your opinion or
    classifications seriously.

    That's fine. I don't take your dismissal of built-in Print (and Read) seriously either.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Wed Sep 30 01:33:16 2026
    From Newsgroup: comp.lang.c

    On 29/09/2026 22:37, Dan Cross wrote:

    There is a lot to be said for the terseness of *printf formatting,
    particularly with compilers that check the type correctness of the printf
    varargs list.

    I'd say the real winning example is `snprintf`, where one can
    format directly into a character array. It is difficult to
    understate the utility this; but if `print` were built into the
    language, you'd lose it, unless you also had a `sprint` builtin.

    Printing to a string works like this:

    [300]char str

    print @str, a, b, c

    In my other language, then `sprint(a, b, c)` will directly return the
    string. Both print and sprint are keywords.

    In that one, a key part is the 'tostr()' operator that stringifies print arguments, and which can be invoked directly.

    However, I can also choose to just call C's 'sprintf'.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Tue Sep 29 22:58:43 2026
    From Newsgroup: comp.lang.c

    On Tue, 29 Sep 2026 15:02:43 +0100, bart wrote:

    On 29/09/2026 08:08, Lawrence DrCOOliveiro wrote:

    So the library routine is still capable of producing meaningful
    results, while the na|>ve implementation still breaks down.

    Any more nitpicks?

    Yes: you're being incredibly pedantic and picky for no reason other
    than to be argumentative and superior.

    YourCOre the one failing to appreciate the point, that it takes smarts
    to design proper numeric algorithms that work within the practical
    *efficient* limits of computer arithmetic.

    These big numbers are ridiculous. If you want to play this game,
    then I've just got my bignum library ...

    So those numbers are rCLridiculousrCY, yet your only way to counter
    them is to be more rCLridiculousrCY?

    Remember, the GNU C routine is capable of giving meaningful results
    over the entire representable range of the real type, without having
    to take the lazy (and slow) way out of resorting to
    higher-precision/magnitude arithmetic.

    So tell me again what is the upper limit when using hypotl()?

    All the way out to the edge, kiddo. All the way out to the edge.

    #include <math.h>
    #include <values.h>
    #include <stdio.h>

    static long double len2(long double x,long double y) { return sqrtl(x*x+y*y);}

    static void compare_for
    (
    long double x
    )
    {
    fprintf
    (
    stdout,
    "for %.7Le: len2 = %.7Le, hypot = %.7Le\n",
    x, len2(x, x), hypotl(x, x)
    );
    } /*compare_for*/

    int main(void)
    {
    fprintf(stdout, "max float value = %.7Le\n", LDBL_MAX);
    compare_for(LDBL_MAX / 1.415);
    compare_for(1.415 / LDBL_MAX);
    return
    0;
    } /*main*/

    raA

    ./naive_hypot_long_double_2
    max float value = 1.1897315e+4932
    for 8.4079964e+4931: len2 = inf, hypot = 1.1890703e+4932
    for 1.1893440e-4932: len2 = 0.0000000e+00, hypot = 1.6819864e-4932
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@profesor.fir@gmail.com to comp.lang.c on Wed Sep 30 02:57:09 2026
    From Newsgroup: comp.lang.c

    Lawrence DrCOOliveiro pisze:
    On Tue, 29 Sep 2026 14:20:23 +0200, fir wrote:

    Lawrence DrCOOliveiro pisze:

    DoesnrCOt correctness of the code figure into your thinking?

    what correctnes?

    We have here a standard library function, already implemented, that
    provides better-quality results than your somewhat simplistic attempt.
    Why should we bother with your code at all?


    why you ask me all that nonsense quiestions?

    maybe i should answer a question to nonsense question then...

    it is your standard of talking?

    on usenet?

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Sep 30 01:54:13 2026
    From Newsgroup: comp.lang.c

    On Tue, 29 Sep 2026 23:59:58 +0100, bart wrote:

    On 29/09/2026 23:49, Lawrence DrCOOliveiro wrote:

    On Tue, 29 Sep 2026 14:36:34 +0100, bart wrote:

    On 29/09/2026 07:38, Lawrence DrCOOliveiro wrote:

    Why? Because <https://en.wikipedia.org/wiki/IEEE_754>. WerCOve
    already discussed elsewhere why implementing it correctly is
    somewhat nontrivial, because the obvious na|>ve implementation is
    prone to be ... somewhat fragile.

    What exactly is incorrect about the naive method? That it stops
    working at a lower magnitude than hypot()?

    hypot() will also stop working at a high enough magnitude; so
    according to you, that is also incorrect?

    Feel free to demonstrate the point at which the library function
    stops working.

    Take your example using hypotl() and remove the '/ 2.0'. (Then the
    answer needs to be about 1.4142 * LDBL_MAX.)

    Or maybe your triangle has a, b sides bigger than LDBL_MAX, or an
    earlier calculation has already overflowed.

    If the only point at which it stops working is the point at which the
    answer becomes unrepresentable anyway, isnrCOt that better than anything
    anyone else in this discussion has been able to offer so far?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Sep 30 01:56:24 2026
    From Newsgroup: comp.lang.c

    On Mon, 28 Sep 2026 20:26:46 +0100, bart wrote:

    I always find it odd when people strive to keep a core language to a
    few dozen keywords to reduce 'cognitive load', but are fine with
    needing to use a library that exports a thousand identifiers, all in
    the same namespace.

    ThatrCOs what rCLmodularityrCY is all about. And why it can be helpful to have selective import, so you only bring in what you need.

    That is, if you really want to use those names without qualification.
    Otherwise just import the module name, and qualify all references to
    its contents with that name. That, too, helps keep namespace pollution
    under control.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Sep 30 02:00:05 2026
    From Newsgroup: comp.lang.c

    On Wed, 30 Sep 2026 02:57:09 +0200, fir wrote:

    Lawrence DrCOOliveiro pisze:

    On Tue, 29 Sep 2026 14:20:23 +0200, fir wrote:

    Lawrence DrCOOliveiro pisze:

    DoesnrCOt correctness of the code figure into your thinking?

    what correctnes?

    We have here a standard library function, already implemented, that
    provides better-quality results than your somewhat simplistic
    attempt. Why should we bother with your code at all?

    why you ask me all that nonsense quiestions?

    ThatrCOs a Donald-Trump-type answer -- attack the questioner as an
    attempt to deflect from the issue at hand.

    Code is not something you write just because it feels good to type in
    all those cryptic symbols. ItrCOs got to do something useful, and
    furthermore, do it correctly.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c on Tue Sep 29 22:09:39 2026
    From Newsgroup: comp.lang.c

    On Tue, 29 Sep 2026 14:36:34 +0100, bart wrote:
    What exactly is incorrect about the naive method? That it stops
    working at a lower magnitude than hypot()?

    It stops working at a MUCH lower magnitude. The naive implementation
    overflows if either argument > sqrt(DBL_MAX). hypot() won't overflow
    until the exact answer is > DBL_MAX. hypot() also avoids unnecessary
    loss of precision when the arguments are very small, though I'm not as
    sure how to characterize that aspect of it.
    hypot() will also stop working at a high enough magnitude; so
    according to you, that is also incorrect?

    It basically won't stop working until the correct answer is no longer representable.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Wed Sep 30 07:02:57 2026
    From Newsgroup: comp.lang.c

    On 2026-09-29 12:11, bart wrote:
    On 29/09/2026 08:03, Janis Papanagnou wrote:
    On 2026-09-28 16:12, David Brown wrote:
    On 28/09/2026 15:38, bart wrote:

    - Always available without needing those annoying #includes (and is
    -a-a it math.h or float.h? I can never remember).

    Other C programmers manage that without effort.

    I seem to recall that on his platform there's no man-pages.
    (Or that he, maybe, dislikes looking into the documentation?
    Sometime he gives that impression.)


    (Funny how shadowing or overriding is usually perceived as bad,
    until you want to shadow something like 'sin' then it's a must-have!)

    Since when is shadowing (or "overriding" in its various forms)
    "perceived as bad"? - I've always seen it as a useful feature.
    And never heard anyone complaining about it.

    It can be useful, it can also introduce subtle bugs if done inadvertently.

    I interpret it that as that you are telling me that *you* introduced
    "subtle bugs". (Okay, we know you, so that is not too surprising. But
    I rather suspect you are just saying that just to make an argument.)


    For example you are using a global name inside a function but also
    happen to define a local of that name, so the global one is hidden.

    That is the point of shadowing! If you introduce a new name in an
    embedded local context you do so to want to refer to that. That's
    the whole point of shadowing that you don't get errors but can use
    a local name instance without interference and without destroying
    a "global" value of the same name.

    Would you prefer a language without hierarchical blocks, scopes,
    and shadowing?! (rhetoric)


    Of you forget to define a local variable and accidentally overwrite, or
    just use, the global version.

    This is obviously your personal problem; operating on something you
    haven't declared is not a problem of shadowing.

    Shadowing is a sensible, useful, and safe concept that appeared with
    block structured, stack oriented languages (I think with Algol 60),
    and which had been inherited for good reasons to most (if not all)
    subsequently appearing languages that support blocks and local scopes.


    You can see the same thing in file systems: [...]

    That is something completely different; you are shifting the goalpost!
    (I won't explain you the PATH concept here, or why it is very useful.
    And some things have already been explained elsethread by Scott.)

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Wed Sep 30 07:59:40 2026
    From Newsgroup: comp.lang.c

    On 2026-09-28 12:43, bart wrote:
    On 28/09/2026 07:45, Lawrence DrCOOliveiro wrote:
    [...]

    You mean a reasonable looking result for quite unreasonable inputs?

    Because it's common to work with triangles whose sides are 170141173319264429905852091742258462720 units long!

    The simple function squares its arguments, so the upper limit for first
    test would be sqrt(FLT_MAX)/2.0 (since it also adds the two squares).

    In that case both versions give the same result. For second test, where
    you are working with triangles with non-zero sides smaller than
    Plancks's Constant, I haven't dealt with.

    Sure, the official version can deal with a wider range, but try it with FLT_MAX and both fail.

    In practice, for inputs this huge, it makes sense to switch to 'double'.

    Then it will also work better for arbitrary expressions that happen to
    use squares and other powers.

    So I think this overhead for 'hypot' is pointless, given that, in
    general, for any 'x' or type float, then x*x /anywhere in a program/
    will overflow when x is bigger than sqrt(FLT_MAX).

    Numeric math is not something I'm doing or that I did professionally.
    So just a few general comments.
    While I think it's nowadays less an issue than in the days of smaller
    'float's there's still high demands from numerical math applications.
    Small differences can change the overall results of a complex numeric
    algorithm significantly; we know that from chaotic systems (weather
    forecasts) or complex hydrodynamic systems (as I've heard from that
    area). In numerical math you need stable functions with good error
    propagation characteristics. And, frankly, I'm not sure I'm nowadays
    as concerned about the MAX being insufficient, rather about whether
    the MIN, the resolution might suffice. Anyway, as I'm no expert in
    that area - and I suppose most programmers are no experts - I'm glad
    that there's competent people who are writing such library functions
    for us that provide the best characteristics for those purposes!
    If you, personally, don't need such stable functions and algorithms
    that's fine. If you don't know where to obtain/find such algorithms,
    whether hypot() or the huge set of functions you find in professional
    math libraries, it may not matter [to you]. (I'm fine with that.)
    But regularly I wonder about your constant complaints, whining, and
    statements about something you don't see or need as being unnecessary.

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Sep 30 07:13:36 2026
    From Newsgroup: comp.lang.c

    On Wed, 30 Sep 2026 00:13:23 +0100, bart wrote:

    On 29/09/2026 23:58, Lawrence DrCOOliveiro wrote:

    On Tue, 29 Sep 2026 15:02:43 +0100, bart wrote:

    On 29/09/2026 08:08, Lawrence DrCOOliveiro wrote:

    So the library routine is still capable of producing meaningful
    results, while the na|>ve implementation still breaks down.

    Any more nitpicks?

    Yes: you're being incredibly pedantic and picky for no reason
    other than to be argumentative and superior.

    YourCOre the one failing to appreciate the point, that it takes
    smarts to design proper numeric algorithms that work within the
    practical *efficient* limits of computer arithmetic.

    OK, so give me a 'smart' square(x) routine where x can go all the
    way to the MAX value.

    Maybe you need to read that paragraph again.

    These big numbers are ridiculous. If you want to play this game,
    then I've just got my bignum library ...

    So those numbers are rCLridiculousrCY, yet your only way to counter
    them is to be more rCLridiculousrCY?

    Yes; they're all ridiculous. You're criticising some line-length
    routine because it goes wrong when deltas reach 10**19 (f32), or
    some 10**153 (f64) or 10**4000 or whatever (f80).

    This is why we have floating-point numbers: so that we can have a
    large dynamic range to cope with things like real physical data.
    WhatrCOs the point of having that range if you canrCOt use most or all of
    it? If, in fact, you can only use a small fraction, but you canrCOt
    actually be sure what fraction that might be, because itrCOs not obvious
    from the function?

    Mine I think will go wrong at 10**5000000000000000000 or something.

    But IT DOESN'T MATTER.

    Yes it does. You forget that, before the widespread adoption of
    IEEE-754, floating-point was a subject ridden with black-magic voodoo
    spells that programmers had to adopt to try to minimize the chance of surprising results on particular machine architectures.

    It took decades for all those quirks to go extinct. Nobody wants them
    back. It seems to be like vaccines: people have forgotten that, if you
    take away the only thing keeping the disease out, you will go back to
    the Bad Old Days of widespread pain and suffering.

    You're also looking at this wrong way: the author of len2() (ie. the
    'naive' version) wrote it with his applications in mind, where its
    spec was perfectly adequate for the job.

    I doubt that particular author had any kind of actual rCLapplicationrCY in mind. If they did, they would have found it simpler to just use the
    existing function, instead of writing their own.

    As the author of a library function, you don't know to what applications
    it will be used for, so you don't make assumptions.

    Precisely the point. That includes making assumptions that the user
    will know that, even though the argument and expected result are both
    within the representable range, some wayward intermediate result will
    cause the whole calculation to blow up and produce a meaningless
    result. When such a misfeature was totally avoidable.

    Also you're not going to get paid much for one line of code so you
    might as well go to town.

    Or, you know, you could avoid wasting everybodyrCOs time, shut up, and
    use the existing wonderful library of readily available,
    well-documented, standards-compliant open-source routines that already
    do the job so well.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Wed Sep 30 09:28:38 2026
    From Newsgroup: comp.lang.c

    On 29/09/2026 23:37, Dan Cross wrote:
    In article <WvUuS.292$M0U7.280@fx10.iad>,
    Scott Lurndal <slp53@pacbell.net> wrote:

    There is a lot to be said for the terseness of *printf formatting,
    particularly with compilers that check the type correctness of the printf
    varargs list.

    I'd say the real winning example is `snprintf`, where one can
    format directly into a character array. It is difficult to
    understate the utility this; but if `print` were built into the
    language, you'd lose it, unless you also had a `sprint` builtin.


    snprintf is the printf family member I use most, and occasionally
    vsnprintf. Other people will likely make heavy use of fprintf too.

    And I often use the return value of printf (or rather, snprintf) to see
    if I've cut the output short.

    So a special language feature for "print" would have to have either
    multiple additional special builtins, or a ridiculously complicated one
    that supports everything in one statement type that differs from all
    normal functions in the language.


    And that's just the start. People like to write their own functions "log_printf", or "debug_printf", with varieties of additional features
    that suit their needs - while still retaining the printf-style
    formatting and the compiler checks of argument types and number.
    Extended standard libraries and OS-specific libraries go further, such
    as having locking systems to avoid mixing output from different threads,
    or cut-down versions without floating point for small microcontrollers.
    A quick glance at newlib's documentation shows 34 functions with
    "printf" in the name. Most people only use a few of them, but all of
    them are useful to someone.



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Wed Sep 30 09:44:15 2026
    From Newsgroup: comp.lang.c

    On 30/09/2026 02:19, bart wrote:
    On 29/09/2026 19:24, David Brown wrote:
    On 29/09/2026 19:15, bart wrote:
    On 29/09/2026 14:56, David Brown wrote:
    On 29/09/2026 13:54, bart wrote:
    My claim is that all these tasks can be done with Print, and it is
    useful to have it as a built-in feature.

    Built-in print is great for "Hello, world!" level programs, and a
    bit beyond that - but it quickly fails for larger needs.

    That is nonsense.

    Such as? Come on, give me a challenge!

    I gave some already.

    Other things include formatted output to log files, formatting of
    different types (not just built-in ones), saving logs in eeprom,
    using different languages for the fixed parts of the strings.
    Basically, anything that the toolchain writer and/or language
    designer didn't think of in the first place.
    And yet some sort of friendlier Print feature is generally provided
    by a language, on top of a set of I/O routines.

    For example Lua has print() as well as io.write. I think Python also
    has 'io', and 'sys', and 'os'.

    So they recognise that providing the simpler Print feature as well
    adds something.

    So do I! I just go further and make it built-in to make even more
    convenient and with nicer syntax.


    There is /nothing/ wrong with making a simple "print" function.

    There is a lot wrong with making it a special language feature,
    instead of a normal function (or other language construct - object,
    template, generic, whatever) that is defined in the standard library,
    using the language itself.

    If you can't make a suitable "print" facility that way, your language
    is weak and limited.

    That's your opinion. You like such features, you like DIY languages, and
    you like lots of moving pieces. In general, you like complexity.


    Your record for speculation about other people's likes and dislikes is
    not improving.

    It is important for a language - a /real/ language used by more than one person - that these things can be library functions written in the
    language itself. It is not important that they, specifically, implement
    them - it is important that /someone/ other than the compiler writer can
    do so.

    No normal C programmer wants to implement their own "printf" in all its
    glory and complexity. But many want it to be possible for /library/ implementers to do so. For example, in microcontroller programming you
    might pick a C library where "printf" does not support floating point,
    because it is then significantly smaller (especially on processors that
    do not have hardware floating point). People who have to use a poor
    quality C compiler like MSVC that does not support C99 can use a
    third-party implementation of printf that /does/ support C99, and useful
    POSIX printf extensions.

    And it is common to write "wrapper" functions for output - functions (or macros) that can take a format string and variadic parameters, use
    snprintf() or similar to do the hard work, then send the output where
    they want. You can only do that if your language supports the
    facilities needed for making your own code in the style of a "print"
    feature. Once you have that in the language, a built-in feature is
    basically pointless.

    Powerful languages don't mean you /have/ to write stuff yourself, or
    that you have to like writing complex code - it also means you can use
    great stuff written by other people.

    And yes, some of the implementation code for these things can be ugly
    and complex - the "user interface" as seen by most C programmers is the "printf" function, not the implementation of it.




    You class everything that is not part of your beloved language as a
    "hack".

    In the case of C, then I've seen enough system header files to
    justifiably call them hacks. In fact I'll go further and call them ugly hacks. That's how C seems to work.

    -a You'll forgive me for not taking your opinion or classifications
    seriously.

    That's fine. I don't take your dismissal of built-in Print (and Read) seriously either.


    That's entirely fair!


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Wed Sep 30 01:00:22 2026
    From Newsgroup: comp.lang.c

    On 9/29/2026 7:01 AM, Janis Papanagnou wrote:
    [...]
    Interesting. - As teenager I also wrote lots of fancy BASIC programs.
    But as soon as Pascal was available that was a lot more fun (for me),
    and a bit step forward! With "C" things degraded, though. (Again, for
    me.)
    As a kid, I used to love making BASIC programs that would create other programs that could be run from EXEC in prodos. Fun times.

    https://www.facebook.com/share/p/19WtuBnkrX/

    Here is a more self-contained version of my generator. It asks you how
    many vertices to enter. Builds CTTEST.BAS, then you can just EXEC
    CTTEST.BAS to run it. Here is my code. Just for fun. The generated code
    draws a bunch of polys using the table LT. Btw, can you get it to work
    on your end?
    _______________________________
    10 REM CREATE NEW PROGRAM FILE
    11 INPUT "Enter Polygon Points: "; N$
    12 LN = ABS(VAL(N$))
    15 PRINT "Generating " + STR$(LN) + "-Gon CTTEST.BAS..."
    20 D$ = CHR$(4)
    25 PRINT D$; "DELETE CTTEST.BAS"
    22 ONERR GOTO 28
    28 POKE 216,0
    30 PRINT D$; "OPEN CTTEST.BAS"
    40 PRINT D$; "WRITE CTTEST.BAS"
    50 REM HOME
    60 PC = 10
    65 PRINT "NEW"
    70 P0$ = "REM " + CHR$(34) + "ct_spawn_test" + CHR$(34): GOSUB 5000
    80 P0$ = "PRINT " + CHR$(34) + "Chris M. Thomasson Spawn" + CHR$(34):
    GOSUB 5000
    101 P0$ = "LN = " + STR$(LN): GOSUB 5000
    120 AB = ATN(1) * 4
    130 SN = (AB * 2) / LN
    140 DIM LT(LN, 2)
    141 P0$ = "DIM LT(" + STR$(LN) + ", 2)": GOSUB 5000
    150 FOR I = 1 TO LN
    160 A = I * SN
    165 LT(I, 1) = COS(A)
    166 LT(I, 2) = SIN(A)
    171 P0$ = "LT(" + STR$(I) + ", 1) = " + STR$(COS(A)): GOSUB 5000
    181 P0$ = "LT(" + STR$(I) + ", 2) = " + STR$(SIN(A)): GOSUB 5000
    290 NEXT I
    300 X0 = 292/2: X1 = 292/6: Y0 = 192/2: Y1 = 192/4
    301 P0$ = "X0 = " + STR$(X0) + ": X1 = " + STR$(X1): GOSUB 5000
    311 P0$ = "Y0 = " + STR$(Y0) + ": Y1 = " + STR$(Y1): GOSUB 5000
    321 P0$ = "HGR : HCOLOR = 3": GOSUB 5000
    430 P0$ = "DIM C0(5)": GOSUB 5000
    441 P0$ = "FOR I = 1 TO LN": GOSUB 5000
    442 P0$ = "C0(1) = X0 + LT(I,1) * 24: C0(2) = Y0 + LT(I,2) * 24: C0(3) =
    .5 * X1: C0(4) = .5 * Y1 :C0(5) = LN: GOSUB 1000": GOSUB 5000
    443 P0$ = "NEXT I": GOSUB 5000
    470 P0$ = "END": GOSUB 5000
    800 PC = 1000
    810 P0$ = "REM PLOT POLY C0(x, y, rx, ry, n)": GOSUB 5000
    820 P0$ = "HPLOT C0(1) + LT(1, 1) * C0(3), C0(2) + LT(1, 2) * C0(4)":
    GOSUB 5000
    830 P0$ = "FOR I0 = 2 TO C0(5)": GOSUB 5000
    840 P0$ = " HPLOT TO C0(1) + LT(I0, 1) * C0(3), C0(2) + LT(I0, 2) *
    C0(4)": GOSUB 5000
    850 P0$ = "NEXT I0": GOSUB 5000
    860 P0$ = "HPLOT TO C0(1) + LT(1, 1) * C0(3), C0(2) + LT(1, 2) * C0(4)":
    GOSUB 5000
    870 P0$ = "RETURN": GOSUB 5000
    890 GOTO 6000
    5000 REM PUSH LINE
    5010 PRINT STR$(PC) + " " + P0$
    5020 PC = PC + 10
    5030 RETURN
    6000 REM CLOSE FILE
    6005 PRINT "RUN"
    6010 PRINT D$; "CLOSE"
    6020 PRINT "Complete! :^)"
    6030 END
    _______________________________

    you can run it here: https://www.scullinsteel.com/apple/e
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@profesor.fir@gmail.com to comp.lang.c on Wed Sep 30 10:08:05 2026
    From Newsgroup: comp.lang.c

    Lawrence DrCOOliveiro pisze:
    On Wed, 30 Sep 2026 02:57:09 +0200, fir wrote:

    Lawrence DrCOOliveiro pisze:

    On Tue, 29 Sep 2026 14:20:23 +0200, fir wrote:

    Lawrence DrCOOliveiro pisze:

    DoesnrCOt correctness of the code figure into your thinking?

    what correctnes?

    We have here a standard library function, already implemented, that
    provides better-quality results than your somewhat simplistic
    attempt. Why should we bother with your code at all?

    why you ask me all that nonsense quiestions?

    ThatrCOs a Donald-Trump-type answer -- attack the questioner as an
    attempt to deflect from the issue at hand.

    Code is not something you write just because it feels good to type in
    all those cryptic symbols. ItrCOs got to do something useful, and furthermore, do it correctly.



    why you ask me idiotic questions and not answer mine?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Wed Sep 30 10:52:59 2026
    From Newsgroup: comp.lang.c

    On 30/09/2026 03:09, James Kuyper wrote:
    On Tue, 29 Sep 2026 14:36:34 +0100, bart wrote:
    What exactly is incorrect about the naive method? That it stops
    working at a lower magnitude than hypot()?

    It stops working at a MUCH lower magnitude. The naive implementation overflows if either argument > sqrt(DBL_MAX).

    Well, so what? You can say that about lots of different expressions and functions!

    If you're the library implementer of something called 'hypot' and don't
    know the range of likely inputs, then you try to make it as bomb-proof
    as possible.

    If you are writing your own for any reason (and here it was to determine
    the length of a vector), then it only has to work for the likely values
    within in your application.

    Even using 'float', that means the inputs need to be below about 18
    billion billion units.

    If that limit is ever broached, you might think about using bigger
    units, or you can do your own scaling.

    However it is usually easier to do the calculation using 'double'. Then
    the limit will involve some 17 successive 'billions'.

    It is a non-issue as far as I'm concerned.

    (I've used floating extensively, starting from when I had to do my own
    FP emulation libraries. I found the problems were with precision rather
    than magnitude. And that was fixed by switching from 32 bits to 64.)

    hypot() won't overflow
    until the exact answer is > DBL_MAX. hypot() also avoids unnecessary
    loss of precision when the arguments are very small, though I'm not as
    sure how to characterize that aspect of it.
    hypot() will also stop working at a high enough magnitude; so
    according to you, that is also incorrect?

    It basically won't stop working until the correct answer is no longer representable.

    It still won't fix the cases where your code needs the value of x*x and
    there is no handy sqrt nearby.

    This is why I don't see the obsession with 'hypot'.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Wed Sep 30 11:35:42 2026
    From Newsgroup: comp.lang.c

    On 30/09/2026 06:02, Janis Papanagnou wrote:
    On 2026-09-29 12:11, bart wrote:

    Would you prefer a language without hierarchical blocks, scopes,
    and shadowing?! (rhetoric)
    I do without block-scopes.

    Of you forget to define a local variable and accidentally overwrite,
    or just use, the global version.

    This is obviously your personal problem;

    Fuck you and your personal vendetta.

    It is a problem for ANYBODY; people make mistakes: they forget, they inadvertently comment out, they make typos, they choose a local that is
    also a needed global.

    Those errors are generally not reported so long as the program is still
    valid.

    Of course, in your world everyone except me is perfect: you never make
    any such errors!

    I'm not arguing against shadowing, just pointing out some issues.


    Here's one of many internet quotes:

    "Variable shadowing happens when a local variable or parameter uses the
    same name as a variable in an outer scope. This causes the inner
    variable to hide (rCLshadowrCY) the outer one, leading to bugs that can
    break your code in subtle ways rCo costing companies millions."

    And another:

    "Variable shadowing itself is not inherently bad. The trouble comes when
    it happens unintentionally,"

    So again, fuck you for your CONSTANT FUCKING PERSONAL INSULTS.


    You can see the same thing in file systems: [...]

    That is something completely different; you are shifting the goalpost!
    (I won't explain you the PATH concept here, or why it is very useful.
    And some things have already been explained elsethread by Scott.)
    No, please do explain how it is different.

    To me it looks the same: a compiler uses some name-resolution scheme
    that works across a hierarchy, so does a file system.

    A file system may choose not to automatically search in the local
    context first: what are the reasons, and could those reasons apply to
    scoped variables too?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Wed Sep 30 12:38:41 2026
    From Newsgroup: comp.lang.c

    On 30/09/2026 11:52, bart wrote:
    On 30/09/2026 03:09, James Kuyper wrote:
    On Tue, 29 Sep 2026 14:36:34 +0100, bart wrote:
    What exactly is incorrect about the naive method? That it stops
    working at a lower magnitude than hypot()?

    It stops working at a MUCH lower magnitude. The naive implementation
    overflows if either argument > sqrt(DBL_MAX).

    Well, so what? You can say that about lots of different expressions and functions!

    If you're the library implementer of something called 'hypot' and don't
    know the range of likely inputs, then you try to make it as bomb-proof
    as possible.

    If you are writing your own for any reason (and here it was to determine
    the length of a vector), then it only has to work for the likely values within in your application.


    Sure.

    But we have been talking about a library - the people using the library
    are not the people who write the library. The people writing the
    library have no idea who will be using it, or for what purpose. Thus
    they aim to make it work for as wide a domain as reasonably feasible.
    And to make things better for their users, they will want to standardise
    it - the same function name in different libraries, different
    programming languages, different target computers will all give the same results for the same values, as specified in the IEEE 754 standards.

    Within one program you might have very different requirements - maybe
    you know particular limits of domains, don't need much accuracy, but
    need everything to be as fast as you can get. That's
    application-specific. There is a famous algorithm for very quickly calculating reciprocal square roots over a limited domain and accuracy -
    great for when that's what you need, but not suitable for a
    general-purpose library reciprocal square root function. (You can
    include the fast one in a library too - it's just not a replacement.)

    It is a non-issue as far as I'm concerned.

    We realise that. But you don't make tools or libraries for other people
    - you can suit yourself.

    This is why I don't see the obsession with 'hypot'.

    It is not an obsession. It's just an example of how good floating point libraries are not simple to implement.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Wed Sep 30 13:41:00 2026
    From Newsgroup: comp.lang.c

    On Wed, 30 Sep 2026 09:28:38 +0200
    David Brown <david.brown@hesbynett.no> wrote:

    On 29/09/2026 23:37, Dan Cross wrote:
    In article <WvUuS.292$M0U7.280@fx10.iad>,
    Scott Lurndal <slp53@pacbell.net> wrote:

    There is a lot to be said for the terseness of *printf formatting,
    particularly with compilers that check the type correctness of the
    printf varargs list.

    I'd say the real winning example is `snprintf`, where one can
    format directly into a character array. It is difficult to
    understate the utility this; but if `print` were built into the
    language, you'd lose it, unless you also had a `sprint` builtin.


    snprintf is the printf family member I use most, and occasionally
    vsnprintf.
    Other people will likely make heavy use of fprintf too.

    And I often use the return value of printf (or rather, snprintf) to
    see if I've cut the output short.



    As was already discussed here 5 years ago, return value of snprintf
    does not fit my most common usage pattern, which is to add strings to
    buffer until it is full and to drop silently the remaining parts after
    buffer is full. I.e. to produce sequences of format calls that behave
    similarly to an individual snprintf.

    Interested reader could still find discussion, including code, by
    searching comp.lang on Google groups for my_snprintf.
    Unfortunately, with recent breakage of GG I no longer can provide a
    working link to either individual article or the thread.


    So a special language feature for "print" would have to have either
    multiple additional special builtins, or a ridiculously complicated
    one that supports everything in one statement type that differs from
    all normal functions in the language.


    And that's just the start. People like to write their own functions "log_printf", or "debug_printf", with varieties of additional
    features that suit their needs - while still retaining the
    printf-style formatting and the compiler checks of argument types and
    number. Extended standard libraries and OS-specific libraries go
    further, such as having locking systems to avoid mixing output from
    different threads, or cut-down versions without floating point for
    small microcontrollers. A quick glance at newlib's documentation
    shows 34 functions with "printf" in the name. Most people only use a
    few of them, but all of them are useful to someone.





    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Wed Sep 30 13:01:16 2026
    From Newsgroup: comp.lang.c

    On 2026-09-30 10:00, Chris M. Thomasson wrote:
    On 9/29/2026 7:01 AM, Janis Papanagnou wrote:
    [...]
    As a kid, I used to love making BASIC programs that would create other programs that could be run from EXEC in prodos. Fun times.

    Sure. :-)

    [...]

    Here is a more self-contained version of my generator. It asks you how
    many vertices to enter. Builds CTTEST.BAS, then you can just EXEC
    CTTEST.BAS to run it. Here is my code. Just for fun. The generated code draws a bunch of polys using the table LT. Btw, can you get it to work
    on your end?

    Bear with me that I don't even try. :-)

    [ snip BASIC program ]

    I mentioned before that as soon as I've got a (much) better language
    (back these days it was Pascal) I (almost) never ever touched BASIC
    again. The one recent exception was a try to transcribe a Lunar Lander application written in some 1960's BASIC to a more "modern" structured language; in my case it was Algol 68. :-p Let me tell you, that was a
    pain. All the spaghetti chaos refactoring to sensible code structures,
    but also the adaption of the old syntax to a new one to be able to use
    an existing BASIC system to verify correctness of the legacy vs. new
    output. At the end it was so much effort that it would have been much
    better to just get the formulas and implement it from scratch instead.

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Wed Sep 30 14:09:48 2026
    From Newsgroup: comp.lang.c

    On Tue, 29 Sep 2026 09:03:37 +0200
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    On 2026-09-28 16:12, David Brown wrote:
    On 28/09/2026 15:38, bart wrote:

    - Always available without needing those annoying #includes (and is
    aa it math.h or float.h? I can never remember).

    Other C programmers manage that without effort.

    I seem to recall that on his platform there's no man-pages.
    (Or that he, maybe, dislikes looking into the documentation?
    Sometime he gives that impression.)


    (Funny how shadowing or overriding is usually perceived as bad,
    until you want to shadow something like 'sin' then it's a
    must-have!)

    Since when is shadowing (or "overriding" in its various forms)
    "perceived as bad"?
    There exist coding standard/style guides that prohibit it. Not just
    MISRA, which I hold at low regard, but some well-thought guids too.
    There are popular compilers that warn about it.
    - I've always seen it as a useful feature.
    And never heard anyone complaining about it.
    It just means that you didn't get out much.
    In decades I also
    don't recall that subtile (or obvious) errors had been reported
    because of that.
    I had seen one yesterday. This particular time it was in context of C++
    member variables and of inheritance. But I certainly had seen similar
    bugs in C. Even made them myself.
    (Are you, yet again, just making things up for
    the argument or have you any different observations from your
    personal coding practice?)

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Wed Sep 30 14:15:45 2026
    From Newsgroup: comp.lang.c

    On Wed, 30 Sep 2026 00:13:23 +0100
    bart <bc@freeuk.com> wrote:
    On 29/09/2026 23:58, Lawrence DrCOOliveiro wrote:
    On Tue, 29 Sep 2026 15:02:43 +0100, bart wrote:

    On 29/09/2026 08:08, Lawrence DrCOOliveiro wrote:

    So the library routine is still capable of producing meaningful
    results, while the na|>ve implementation still breaks down.

    Any more nitpicks?

    Yes: you're being incredibly pedantic and picky for no reason other
    than to be argumentative and superior.

    YourCOre the one failing to appreciate the point, that it takes smarts
    to design proper numeric algorithms that work within the practical *efficient* limits of computer arithmetic.

    OK, so give me a 'smart' square(x) routine where x can go all the way
    to the MAX value.

    Come on. You are certainly good enough programmer to figure it out
    yourself. It should not take more than few minutes.
    If you want hint, it is in the followup.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Wed Sep 30 14:18:35 2026
    From Newsgroup: comp.lang.c

    On Wed, 30 Sep 2026 14:15:45 +0300
    Michael S <already5chosen@yahoo.com> wrote:
    On Wed, 30 Sep 2026 00:13:23 +0100
    bart <bc@freeuk.com> wrote:

    On 29/09/2026 23:58, Lawrence DrCOOliveiro wrote:
    On Tue, 29 Sep 2026 15:02:43 +0100, bart wrote:

    On 29/09/2026 08:08, Lawrence DrCOOliveiro wrote:

    So the library routine is still capable of producing meaningful
    results, while the na|>ve implementation still breaks down.

    Any more nitpicks?

    Yes: you're being incredibly pedantic and picky for no reason
    other than to be argumentative and superior.

    YourCOre the one failing to appreciate the point, that it takes
    smarts to design proper numeric algorithms that work within the
    practical *efficient* limits of computer arithmetic.

    OK, so give me a 'smart' square(x) routine where x can go all the
    way to the MAX value.


    Come on. You are certainly good enough programmer to figure it out
    yourself. It should not take more than few minutes.

    If you want hint, it is in the followup.

    frexp
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Wed Sep 30 14:32:23 2026
    From Newsgroup: comp.lang.c

    On Tue, 29 Sep 2026 22:58:43 -0000 (UTC)
    Lawrence DrCOOliveiro <ldo@nz.invalid> wrote:
    On Tue, 29 Sep 2026 15:02:43 +0100, bart wrote:

    On 29/09/2026 08:08, Lawrence DrCOOliveiro wrote:

    So the library routine is still capable of producing meaningful
    results, while the na|>ve implementation still breaks down.

    Any more nitpicks?

    Yes: you're being incredibly pedantic and picky for no reason other
    than to be argumentative and superior.

    YourCOre the one failing to appreciate the point, that it takes smarts
    to design proper numeric algorithms that work within the practical *efficient* limits of computer arithmetic.

    These big numbers are ridiculous. If you want to play this game,
    then I've just got my bignum library ...

    So those numbers are rCLridiculousrCY, yet your only way to counter
    them is to be more rCLridiculousrCY?

    Remember, the GNU C routine is capable of giving meaningful results
    over the entire representable range of the real type, without having
    to take the lazy (and slow) way out of resorting to higher-precision/magnitude arithmetic.
    Pay attention that GNU C is a compiler + comiler support library
    (libgcc).
    hyport() is part of Standard C library, which is not a part of either.
    Some of C Libraries used with GCC can do what you calaim. Others can be
    less great at covering full range. Yet others can cover full range by
    means of using higher preccision or magnitude. On some platforms,
    including some which are popular, the latter could be even a good
    idea.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Wed Sep 30 13:55:42 2026
    From Newsgroup: comp.lang.c

    On 30/09/2026 13:09, Michael S wrote:
    On Tue, 29 Sep 2026 09:03:37 +0200
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 2026-09-28 16:12, David Brown wrote:
    On 28/09/2026 15:38, bart wrote:

    - Always available without needing those annoying #includes (and is
    -a-a it math.h or float.h? I can never remember).

    Other C programmers manage that without effort.

    I seem to recall that on his platform there's no man-pages.
    (Or that he, maybe, dislikes looking into the documentation?
    Sometime he gives that impression.)


    (Funny how shadowing or overriding is usually perceived as bad,
    until you want to shadow something like 'sin' then it's a
    must-have!)

    Since when is shadowing (or "overriding" in its various forms)
    "perceived as bad"?

    There exist coding standard/style guides that prohibit it. Not just
    MISRA, which I hold at low regard, but some well-thought guids too.
    There are popular compilers that warn about it.

    - I've always seen it as a useful feature.
    And never heard anyone complaining about it.

    It just means that you didn't get out much.


    Poorly considered or unintentional shadowing can certainly lead to bugs
    or programmer confusion.

    Equally, however, it is an essential feature to long-term programming. Otherwise you have to make sure you pick names for all your local
    identifiers that could never be included in any of the headers
    (application, third-party library, standard library, whatever) used by
    your code. That means avoiding any names that might be used in /future/ versions of these headers, or in headers from other platforms or toolchains.

    Clearly that is infeasible - it would place unreasonable restraints on
    how you could write your own code, and unreasonable restraints on how libraries and other code could write their headers.

    Just as clearly, you should not knowingly shadow an existing name unless that's the choice that is clearest in the code.

    Long ago, I used "-Wshadow" in gcc but stopped due to too many false positives. (Many <math.h> libraries include Bessel functions like "y0"
    and "y1" when not used in strict standards modes, though these are
    popular identifiers for local variables or parameters.) Current gcc has
    more nuanced versions like "-Wshadow=local" and
    "-Wshadow=compatible-local" which are often a better choice.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From fir@profesor.fir@gmail.com to comp.lang.c on Wed Sep 30 13:58:45 2026
    From Newsgroup: comp.lang.c

    fir pisze:
    Lawrence DrCOOliveiro pisze:
    On Wed, 30 Sep 2026 02:57:09 +0200, fir wrote:

    Lawrence DrCOOliveiro pisze:

    On Tue, 29 Sep 2026 14:20:23 +0200, fir wrote:

    Lawrence DrCOOliveiro pisze:

    DoesnrCOt correctness of the code figure into your thinking?

    what correctnes?

    We have here a standard library function, already implemented, that
    provides better-quality results than your somewhat simplistic
    attempt. Why should we bother with your code at all?

    why you ask me all that nonsense quiestions?

    ThatrCOs a Donald-Trump-type answer -- attack the questioner as an
    attempt to deflect from the issue at hand.

    Code is not something you write just because it feels good to type in
    all those cryptic symbols. ItrCOs got to do something useful, and
    furthermore, do it correctly.



    why you ask me idiotic questions and not answer mine?



    ok im 'trolling' you (i mean make fun wit your stupid behaviour)
    you come hera ask idiotic question - idiotic questions do not prove any
    stupid point and overally are slightly harmfull for this group too
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Wed Sep 30 14:14:07 2026
    From Newsgroup: comp.lang.c

    On 2026-09-30 12:35, bart wrote:
    On 30/09/2026 06:02, Janis Papanagnou wrote:
    On 2026-09-29 12:11, bart wrote:

    Would you prefer a language without hierarchical blocks, scopes,
    and shadowing?! (rhetoric)

    I do without block-scopes.

    We know you are doing a lot things and omitting yet more things than
    other experienced CS folks. I wonder that you still think the Sun is
    rotating around the Earth.


    Of you forget to define a local variable and accidentally overwrite,
    or just use, the global version.

    This is obviously your personal problem;

    Fuck you and your personal vendetta.

    You are again hallucinating things that are non-existing.


    It is a problem for ANYBODY; people make mistakes: they forget, they inadvertently comment out, they make typos, they choose a local that is
    also a needed global.

    You are again making unsubstantiated statements about "anybody" and
    "people" in general. - All we can see is that obviously *you* have a
    problem here where others don't. (Call it [wrongly] "vendetta" if it
    makes you feel better and continue with your ignorance, it won't
    change the world.)


    Those errors are generally not reported so long as the program is still valid.

    You are very generous with such "general" statements. You've regularly demonstrated that you have actually no clue about the world outside
    your bubble and limited imagination, and (only?) stubbornness hinders
    you to acknowledge reports about the concrete (CS and IT) world. - If
    you'd be just a bit smarter you'd recognize that you cannot in principle
    and substantially backup such claims.


    Of course, in your world everyone except me is perfect: you never make
    any such errors!

    Again a standard phrase as a result of your pathological mental stance.
    You make up stupid wrong generalizing statements about "everyone" that
    no one has ever said or assumed.

    You seem to be assuming that scopes are bad, and the consequent design decisions of shadowing in block oriented scoped languages a collective
    bad design decision of the language designer, scientists, and language
    users (the programmers). - Can you, for a moment, shut up (i.e. not
    immediately write another post), and take the time pondering about the situation. - Is your hubris really so huge, your recognition of all the existing expertise so non-existent, and your perception that impaired?
    (again rhetoric; but you like to answer anyway as we saw above)


    I'm not arguing against shadowing, just pointing out some issues.


    Here's one of many internet quotes:

    "Variable shadowing happens when a local variable or parameter uses the
    same name as a variable in an outer scope. This causes the inner
    variable to hide (rCLshadowrCY) the outer one, leading to bugs that can break your code in subtle ways rCo costing companies millions."

    This looks like an unsubstantiated AI quote.


    And another:

    "Variable shadowing itself is not inherently bad. The trouble comes when
    it happens unintentionally,"

    This has already been addressed, but you still quote it; why? - I see
    that the relevant part is not explained, there's no substance.

    Both quotes are vague ("leading to bugs that can break your code in
    subtle ways", "it happens unintentionally") and just FUD.


    So again, fuck you for your CONSTANT FUCKING PERSONAL INSULTS.

    You mean when I point out that you are hallucinating, presenting your
    personal opinions as facts, don't give substantiated arguments, make
    wrong presumptions about what people think, making wrong generalizing
    claims, quote non-substantiated statements from own brain or from the
    net arbitrarily. - I'd really appreciate if you'd omit all that; it
    would make communication with you much easier. But sadly, despite you
    are regularly hinted at that, to omit that, you continue that way. -
    What do you expect? (rhetoric again)



    You can see the same thing in file systems: [...]

    That is something completely different; you are shifting the goalpost!
    (I won't explain you the PATH concept here, or why it is very useful.
    And some things have already been explained elsethread by Scott.)
    No, please do explain how it is different.

    To me it looks the same: a compiler uses some name-resolution scheme
    that works across a hierarchy, so does a file system.

    But they are factually completely different. - The PATH is there to
    primarily address _dedicated_ locations for executable programs. It
    defines a strict precedence, say, that a user's $HOME/bin program
    takes precedence over a system binary, or that a global 'local/bin'
    installed software has precedence over the system installation. Its
    purpose is to control the "precedence path". And a user can define
    that in any way he seems it best fitting. - In scoped nested blocks
    it's a completely different intention and logic; the programmer does
    not need to know or track every variable instance, he can generally
    operate locally without affecting the surrounding variables. Say, you
    need an index, just declare "int i;" and use it; it won't affect any
    'i' declared on some outer, distinct, external, wherever item. You are completely safe. And if you're leaving that scope no other variable
    with the same name in the reach of the environment is tackled. That's
    really a great principle! (And hard to imaging to have no blocks with
    scope and shadowing when we want to do safe structured programming.)

    Actually, since you made up that (IMO inappropriate) PATH comparison;
    if you want to compare the shadowing with Unix mechanisms consider
    the environment variables instead; they can be exported to sub-shells,
    you can declare your own variables in sub-processes, none affects any
    outer variables. - This as well is not the same as shadowing in scopes
    of blocks but it better explains about the principle concept to have
    changes in sub-components of hierarchical structures not affecting the environment, the "outer blocks". - Try to understand that principle
    that we can find in many (also non-IT) places; it really makes sense.
    And, again, before getting rabid again and send another post, *please*
    _think about it_.

    (I don't believe you will be able to change your habit or even become enlightened, but... - well, we'll see.)


    A file system may choose not to automatically search in the local
    context first: what are the reasons, and could those reasons apply to
    scoped variables too?

    This statement shows that you are completely uninformed about what you
    have chosen to pick as comparison. - I'm sure I've read it had already
    been answered elsethread. Why do you ignore that? Why don't you inform
    yourself before making false and stupid statements? (rhetoric)

    (You're amazingly ignorant, and obviously keen to maintain that state.)

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Wed Sep 30 13:24:47 2026
    From Newsgroup: comp.lang.c

    On 30/09/2026 12:18, Michael S wrote:
    On Wed, 30 Sep 2026 14:15:45 +0300
    Michael S <already5chosen@yahoo.com> wrote:

    On Wed, 30 Sep 2026 00:13:23 +0100
    bart <bc@freeuk.com> wrote:

    On 29/09/2026 23:58, Lawrence DrCOOliveiro wrote:
    On Tue, 29 Sep 2026 15:02:43 +0100, bart wrote:

    On 29/09/2026 08:08, Lawrence DrCOOliveiro wrote:

    So the library routine is still capable of producing meaningful
    results, while the na|>ve implementation still breaks down.

    Any more nitpicks?

    Yes: you're being incredibly pedantic and picky for no reason
    other than to be argumentative and superior.

    YourCOre the one failing to appreciate the point, that it takes
    smarts to design proper numeric algorithms that work within the
    practical *efficient* limits of computer arithmetic.

    OK, so give me a 'smart' square(x) routine where x can go all the
    way to the MAX value.


    Come on. You are certainly good enough programmer to figure it out
    yourself. It should not take more than few minutes.

    If you want hint, it is in the followup.


    frexp


    I don't see how that helps. My made-up square function has a signature
    like (T)->T, and T will have a particular T.MAX value.

    So, what is the maximum input that can yield a result that can still be represented within a type T? Presumably it is +/- sqrt(T.MAX).

    The broader point is that pretty much any arithmetic involving floats
    can overflow the range if the magnitudes are large enough (or small
    enough with divide etc).

    You can still work with this, since the ranges of f32 and especially f64
    are generous enough. (And if using the x87 FPU, intermediates use f80.)

    In the very, very specific case of hypot, then being able to work with
    as large a range as possible via clever tricks is great, but there is no
    great practical need.

    Certainly not enough to dismiss the 'naive' solution out of hand,
    especially if it is faster.


    I stated elsewhere that I often worked with 'x*x + y*y' without
    bothering with the square root, so here that cleverness won't help.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Wed Sep 30 14:31:40 2026
    From Newsgroup: comp.lang.c

    On 2026-09-30 13:09, Michael S wrote:
    On Tue, 29 Sep 2026 09:03:37 +0200
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    On 2026-09-28 16:12, David Brown wrote:
    On 28/09/2026 15:38, bart wrote:

    - Always available without needing those annoying #includes (and is
    -a-a it math.h or float.h? I can never remember).

    Other C programmers manage that without effort.

    I seem to recall that on his platform there's no man-pages.
    (Or that he, maybe, dislikes looking into the documentation?
    Sometime he gives that impression.)


    (Funny how shadowing or overriding is usually perceived as bad,
    until you want to shadow something like 'sin' then it's a
    must-have!)

    Since when is shadowing (or "overriding" in its various forms)
    "perceived as bad"?

    There exist coding standard/style guides that prohibit it. Not just
    MISRA, which I hold at low regard, but some well-thought guids too.

    Interesting. (The ones I've seen certainly didn't have such an IMO
    absolutely stupid rule.) - Were there any rationales for the rules?
    (I mean if you take away a sensible concept from a language there
    should at least be some severe problems we want to prevent. Which?)

    There are popular compilers that warn about it.

    That is fair, IMO, if you can control and deactivate that behavior.

    But I've also seen compilers that were annoyingly persisting in
    those "warnings". In one case I was able to convince the maintainer
    to remove that annoying warning, though.


    - I've always seen it as a useful feature.
    And never heard anyone complaining about it.

    It just means that you didn't get out much.

    LOL - maybe. :-)

    But given that I have a comparably wide-ranging experience in a lot
    of different business-areas, IT-areas, IT-companies, and IT-projects
    over many decades, I'm indeed wondering about that.

    Seriously, I've seen folks complain about everything. We should have
    a clear view on who complains and how substantiated the complaints are.


    In decades I also
    don't recall that subtile (or obvious) errors had been reported
    because of that.

    I had seen one yesterday. This particular time it was in context of C++ member variables and of inheritance. But I certainly had seen similar
    bugs in C. Even made them myself.

    Well, inheritance is not as shadowing; you can explicitly qualify the
    access to inherited attributes!

    Or how did these problems look like? - And how do you solve it? - By
    renaming, say, hierarchical index variables 'i' to 'i1', 'i2', etc.?

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Wed Sep 30 14:45:08 2026
    From Newsgroup: comp.lang.c

    On 2026-09-30 14:24, bart wrote:

    I stated elsewhere that I often worked with 'x*x + y*y' without
    bothering with the square root, so here that cleverness won't help.

    Sure. Another function, another conditions. - Shifted goalpost from
    hypot() to something else.

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Wed Sep 30 13:45:51 2026
    From Newsgroup: comp.lang.c

    On 30/09/2026 13:14, Janis Papanagnou wrote:


    You mean when I point out that you are hallucinating, presenting your personal opinions as facts,

    About shadowing? Michael S made similar remarks to mine. Perhaps he's hallucinating too.

    To me it looks the same: a compiler uses some name-resolution scheme
    that works across a hierarchy, so does a file system.

    But they are factually completely different.

    Is there a hierarchy in both cases?

    Is there a scheme/algorithm involved in both cases?

    Is there a way to override or control behaviour in both cases?

    Is there way to denote qualifier chains in both cases? (Eg. a/b/c
    or a.b.c)

    The answers are Yes or No to each.

    If they are all Yes than they are not 'completely different'.

    The details are not relevant - we know that a file system is not
    language source code.

    (I don't believe you will be able to change your habit or even become enlightened, but... - well, we'll see.)

    Sadly you're not going to change /your/ habits. What a nasty, vindictive
    attitude you have.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Wed Sep 30 15:56:05 2026
    From Newsgroup: comp.lang.c

    On Wed, 30 Sep 2026 13:24:47 +0100
    bart <bc@freeuk.com> wrote:
    On 30/09/2026 12:18, Michael S wrote:
    On Wed, 30 Sep 2026 14:15:45 +0300
    Michael S <already5chosen@yahoo.com> wrote:

    On Wed, 30 Sep 2026 00:13:23 +0100
    bart <bc@freeuk.com> wrote:

    On 29/09/2026 23:58, Lawrence DrCOOliveiro wrote:
    On Tue, 29 Sep 2026 15:02:43 +0100, bart wrote:

    On 29/09/2026 08:08, Lawrence DrCOOliveiro wrote:

    So the library routine is still capable of producing meaningful
    results, while the na|>ve implementation still breaks down.

    Any more nitpicks?

    Yes: you're being incredibly pedantic and picky for no reason
    other than to be argumentative and superior.

    YourCOre the one failing to appreciate the point, that it takes
    smarts to design proper numeric algorithms that work within the
    practical *efficient* limits of computer arithmetic.

    OK, so give me a 'smart' square(x) routine where x can go all the
    way to the MAX value.


    Come on. You are certainly good enough programmer to figure it out
    yourself. It should not take more than few minutes.

    If you want hint, it is in the followup.


    frexp


    I don't see how that helps.
    I don't see exactly what it is that you don't see. Remember: we are
    talking about a specific thing rCo the `hypot()` function. Try to resist
    the urge to confuse us with unnecessary generalizations.
    My made-up square function has a
    signature like (T)->T, and T will have a particular T.MAX value.

    So, what is the maximum input that can yield a result that can still
    be represented within a type T? Presumably it is +/- sqrt(T.MAX).

    The broader point is that pretty much any arithmetic involving floats
    can overflow the range if the magnitudes are large enough (or small
    enough with divide etc).

    The narrower point is that for some of *standard* library functions
    covering range as close as possible to mathematically meaningful input
    range is a requirement.
    In specific case of hypot() + C Standard there are no strict
    requirements like those. However some other Standards, e.g. POSIX, are
    more strict, although still not quite as strict as my above formulation.
    You can still work with this, since the ranges of f32 and especially
    f64 are generous enough. (And if using the x87 FPU, intermediates use
    f80.)

    In the very, very specific case of hypot, then being able to work
    with as large a range as possible via clever tricks is great, but
    there is no great practical need.

    Certainly not enough to dismiss the 'naive' solution out of hand,
    especially if it is faster.


    I stated elsewhere that I often worked with 'x*x + y*y' without
    bothering with the square root, so here that cleverness won't help.
    It can help even here but in less obvious ways.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Wed Sep 30 16:12:25 2026
    From Newsgroup: comp.lang.c

    On Wed, 30 Sep 2026 14:31:40 +0200
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:


    Well, inheritance is not as shadowing; you can explicitly qualify the
    access to inherited attributes!

    It's not an *absolute* shadowing, yes. Which makes matters worse,
    because compiler is less likely to warn you.


    Or how did these problems look like? - And how do you solve it? - By renaming, say, hierarchical index variables 'i' to 'i1', 'i2', etc.?

    Janis


    There was a member variable in the base class and member variable with
    the same name in derived class.
    The programmer accessed (wrote to) a member of derived when his actual intention was to access the one of base. Then he wondered why the value
    in the base instance is wrong.
    Since it was just a mistake, a fix was easy - removing the offending
    member from declaration of derived class. But finding the bug was not
    easy.





    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Wed Sep 30 15:30:29 2026
    From Newsgroup: comp.lang.c

    On 30/09/2026 14:45, bart wrote:
    On 30/09/2026 13:14, Janis Papanagnou wrote:


    You mean when I point out that you are hallucinating, presenting your
    personal opinions as facts,

    About shadowing? Michael S made similar remarks to mine. Perhaps he's hallucinating too.

    Michael wrote that /sometimes/ shadowing hides bugs that might otherwise
    have been noticed by the programmer and/or trigger a compilation error.
    And some people and coding standards actively avoid shadowing.

    That's all fair.

    And it also shows that it is personal opinion - even when multiple
    people happen to share the same opinion. Janis's opinions on shadowing
    are no more or less factual than yours, and no more or less valid. You
    can dislike shadowing if you want, you can disable it in your language
    if you want, use "gcc -Wshadow" if you want. But be careful about
    turning your preferences and personal experiences into generalisations
    and assuming they apply to others. (I have been known to do that myself
    from time to time - it does not mean it is a good thing!)

    (I don't believe Michael gave his own preferences for whether or not to
    try to avoid shadowing. I'm guessing he aims to pick his identifier
    names in a way that makes his code as clear as he can reasonably make
    it, unless he is required to follow a style guide with rules on the matter.)

    Support for shadowing is the norm for languages with scoped identifiers
    - identifiers in inner scopes can shadow those of outer scopes. Things
    can be complicated when there are multiple types of scope in a language,
    but shadowing is pretty much essential for scalability of a language,
    even though it can usually be avoided.

    gcc has warnings "-Wshadow-compatible-local" and "-Wshadow=local" which
    warn on local variables shadowing each other, which can be a good
    compromise for what to avoid without risking false positives. But it's
    a personal style choice.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Wed Sep 30 17:14:40 2026
    From Newsgroup: comp.lang.c

    On Wed, 30 Sep 2026 15:30:29 +0200
    David Brown <david.brown@hesbynett.no> wrote:

    On 30/09/2026 14:45, bart wrote:
    On 30/09/2026 13:14, Janis Papanagnou wrote:


    You mean when I point out that you are hallucinating, presenting
    your personal opinions as facts,

    About shadowing? Michael S made similar remarks to mine. Perhaps
    he's hallucinating too.

    Michael wrote that /sometimes/ shadowing hides bugs that might
    otherwise have been noticed by the programmer and/or trigger a
    compilation error. And some people and coding standards actively
    avoid shadowing.

    That's all fair.

    And it also shows that it is personal opinion - even when multiple
    people happen to share the same opinion. Janis's opinions on
    shadowing are no more or less factual than yours, and no more or less
    valid. You can dislike shadowing if you want, you can disable it in
    your language if you want, use "gcc -Wshadow" if you want. But be
    careful about turning your preferences and personal experiences into generalisations and assuming they apply to others. (I have been
    known to do that myself from time to time - it does not mean it is a
    good thing!)

    (I don't believe Michael gave his own preferences for whether or not
    to try to avoid shadowing. I'm guessing he aims to pick his
    identifier names in a way that makes his code as clear as he can
    reasonably make it, unless he is required to follow a style guide
    with rules on the matter.)

    Support for shadowing is the norm for languages with scoped
    identifiers
    - identifiers in inner scopes can shadow those of outer scopes.

    Generally yes, but there exist variations.
    For example, in C# local variable in the inner block is not allowed to
    to have the same name as local variable in the outer score.

    Rust is extreme in opposite direction - shadowing is allowed even
    without creation of the new block. Although in this case shadowing is,
    may be, not the best name.

    Things can be complicated when there are multiple types of scope in a language, but shadowing is pretty much essential for scalability of a language, even though it can usually be avoided.

    gcc has warnings "-Wshadow-compatible-local" and "-Wshadow=local"
    which warn on local variables shadowing each other, which can be a
    good compromise for what to avoid without risking false positives.
    But it's a personal style choice.



    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Wed Sep 30 16:42:09 2026
    From Newsgroup: comp.lang.c

    On 30/09/2026 16:14, Michael S wrote:
    On Wed, 30 Sep 2026 15:30:29 +0200
    David Brown <david.brown@hesbynett.no> wrote:

    On 30/09/2026 14:45, bart wrote:
    On 30/09/2026 13:14, Janis Papanagnou wrote:


    You mean when I point out that you are hallucinating, presenting
    your personal opinions as facts,

    About shadowing? Michael S made similar remarks to mine. Perhaps
    he's hallucinating too.

    Michael wrote that /sometimes/ shadowing hides bugs that might
    otherwise have been noticed by the programmer and/or trigger a
    compilation error. And some people and coding standards actively
    avoid shadowing.

    That's all fair.

    And it also shows that it is personal opinion - even when multiple
    people happen to share the same opinion. Janis's opinions on
    shadowing are no more or less factual than yours, and no more or less
    valid. You can dislike shadowing if you want, you can disable it in
    your language if you want, use "gcc -Wshadow" if you want. But be
    careful about turning your preferences and personal experiences into
    generalisations and assuming they apply to others. (I have been
    known to do that myself from time to time - it does not mean it is a
    good thing!)

    (I don't believe Michael gave his own preferences for whether or not
    to try to avoid shadowing. I'm guessing he aims to pick his
    identifier names in a way that makes his code as clear as he can
    reasonably make it, unless he is required to follow a style guide
    with rules on the matter.)

    Support for shadowing is the norm for languages with scoped
    identifiers
    - identifiers in inner scopes can shadow those of outer scopes.

    Generally yes, but there exist variations.
    For example, in C# local variable in the inner block is not allowed to
    to have the same name as local variable in the outer score.


    I don't know C#, so thanks for that information.

    Rust is extreme in opposite direction - shadowing is allowed even
    without creation of the new block. Although in this case shadowing is,
    may be, not the best name.


    I have always thought it would be nice in C and C++, to be able to
    re-declare variables (especially const "variables") without having to be
    able to introduce new blocks :

    const int data = get_next();
    do_first_thing(data);

    const int data = get_next();
    do_second_thing(data);

    (The semantics would be basically as though a new block was introduced
    before the pair of lines. Then let the compiler's lifetime analysis
    handle efficient re-use of registers and stack slots.)

    While it could lead to confusing code sometimes, I think it could also
    be helpful in code that has repetitive patterns. As it is, you need to
    either have new names, make the variable non-const, or include extra
    blocks around the sections. I'd be quite happy if this were restricted
    to "const" objects.

    Is that the sort of thing Rust allows here?

    Things can be complicated when there are multiple types of scope in a
    language, but shadowing is pretty much essential for scalability of a
    language, even though it can usually be avoided.

    gcc has warnings "-Wshadow-compatible-local" and "-Wshadow=local"
    which warn on local variables shadowing each other, which can be a
    good compromise for what to avoid without risking false positives.
    But it's a personal style choice.




    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Wed Sep 30 18:02:37 2026
    From Newsgroup: comp.lang.c

    On Wed, 30 Sep 2026 16:42:09 +0200
    David Brown <david.brown@hesbynett.no> wrote:

    On 30/09/2026 16:14, Michael S wrote:
    Rust is extreme in opposite direction - shadowing is allowed even
    without creation of the new block. Although in this case shadowing
    is, may be, not the best name.


    I have always thought it would be nice in C and C++, to be able to re-declare variables (especially const "variables") without having to
    be able to introduce new blocks :

    const int data = get_next();
    do_first_thing(data);

    const int data = get_next();
    do_second_thing(data);

    (The semantics would be basically as though a new block was
    introduced before the pair of lines. Then let the compiler's
    lifetime analysis handle efficient re-use of registers and stack
    slots.)

    While it could lead to confusing code sometimes, I think it could
    also be helpful in code that has repetitive patterns. As it is, you
    need to either have new names, make the variable non-const, or
    include extra blocks around the sections. I'd be quite happy if this
    were restricted to "const" objects.

    Is that the sort of thing Rust allows here?


    Yes, but it allows mutables as well. And different types.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Wed Sep 30 16:54:08 2026
    From Newsgroup: comp.lang.c

    On 30/09/2026 14:30, David Brown wrote:
    On 30/09/2026 14:45, bart wrote:
    On 30/09/2026 13:14, Janis Papanagnou wrote:


    You mean when I point out that you are hallucinating, presenting your
    personal opinions as facts,

    About shadowing? Michael S made similar remarks to mine. Perhaps he's
    hallucinating too.

    Michael wrote that /sometimes/ shadowing hides bugs that might otherwise have been noticed by the programmer and/or trigger a compilation error.
    And some people and coding standards actively avoid shadowing.

    That's all fair.

    And it also shows that it is personal opinion - even when multiple
    people happen to share the same opinion.-a Janis's opinions on shadowing
    are no more or less factual than yours, and no more or less valid.-a You
    can dislike shadowing if you want,


    I didn't give my opinions on it. I pointed out some issues with it.
    Examples:

    BC (me):

    It can be useful, it can also introduce subtle bugs if done
    inadvertently.

    JP:
    I interpret it that as that you are telling me that *you* introduced
    "subtle bugs". (Okay, we know you, so that is not too surprising. But
    I rather suspect you are just saying that just to make an argument.)

    BC:
    Of you forget to define a local variable and accidentally overwrite,
    or just use, the global version.

    JP:
    This is obviously your personal problem; operating on something you
    haven't declared is not a problem of shadowing.


    JP about possible issues with shadowing:

    And never heard anyone complaining about it.

    In decades I also
    don't recall that subtile (or obvious) errors had been reported
    because of that. (Are you, yet again, just making things up for
    the argument or have you any different observations from your
    personal coding practice?)

    Every single riposte from JP has to be a personal barb and insult, and
    of course dismisses my point 100% out of hand. Something wrong there.


    you can disable it in your language
    if you want,

    I don't like that inadvertent shadowing that leads to odd bugs isn't
    reported. But that is how it has worked for decades.

    (However, one feature I have which is out-of-order definitions, together
    with the ability to omit having a main() wrapper around top-level
    executable statement, is very susceptible to such errors. So that has
    been banned on one language and in another is only used for throwaway programs.)

    Clashes between the same imported name /are/ detected, so that I know to
    do something about it. Another approach would be to silently use the
    first match.

    (I don't know what languages do that other than Python using 'from'
    imports. I don't know enough C++ to try it out via 'using'.)


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Wed Sep 30 17:12:50 2026
    From Newsgroup: comp.lang.c

    On 30/09/2026 13:14, Janis Papanagnou wrote:
    On 2026-09-30 12:35, bart wrote:
    On 30/09/2026 06:02, Janis Papanagnou wrote:
    On 2026-09-29 12:11, bart wrote:

    Would you prefer a language without hierarchical blocks, scopes,
    and shadowing?! (rhetoric)

    I do without block-scopes.

    We know you are doing a lot things and omitting yet more things than
    other experienced CS folks.

    Python doesn't have block scopes either. I believe they are (or were)
    missing from JavaScript too.

    Those are both one-man languages but perhaps you've heard of them.

    I wonder that you still think the Sun is
    rotating around the Earth.
    Why don't you ask the creators of the two languages I mentioned?

    Some people are just sheep and follow the crowd without any ideas or
    opinions of their own. But some of them like to attack those who do.

    <Braces for another onslaught of abuse.>

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Wed Sep 30 18:26:43 2026
    From Newsgroup: comp.lang.c

    On 30/09/2026 17:54, bart wrote:
    On 30/09/2026 14:30, David Brown wrote:
    On 30/09/2026 14:45, bart wrote:
    On 30/09/2026 13:14, Janis Papanagnou wrote:


    And it also shows that it is personal opinion - even when multiple
    people happen to share the same opinion.-a Janis's opinions on
    shadowing are no more or less factual than yours, and no more or less
    valid.-a You can dislike shadowing if you want,


    I didn't give my opinions on it. I pointed out some issues with it.

    OK. Let's drop this - nothing useful can be gained from continuing this
    bit.

    you can disable it in your language if you want,

    I don't like that inadvertent shadowing that leads to odd bugs isn't reported. But that is how it has worked for decades.

    (However, one feature I have which is out-of-order definitions, together with the ability to omit having a main() wrapper around top-level
    executable statement, is very susceptible to such errors. So that has
    been banned on one language and in another is only used for throwaway programs.)

    Out-of-order definitions within a scope is susceptible to a lot of
    risks, unless it is quite restricted. In particular, I would restrict
    it to constant "things" - constant objects and functions, and perhaps
    types. I would hate to figure out what is going on with "x = 2;"
    followed by "int x = 3;" in the same scope. (Maybe you don't allow initialisation in variable definitions?)


    Clashes between the same imported name /are/ detected, so that I know to
    do something about it. Another approach would be to silently use the
    first match.


    Noisy errors on clashes are a good idea if there is no clear and
    consistent ordering.

    (I don't know what languages do that other than Python using 'from'
    imports. I don't know enough C++ to try it out via 'using'.)


    Python is always a bit special in that it does not have the same
    compile-time / run-time distinction as C. It actually requires that all identifiers are defined (bound) before use - but identifiers within a
    block in a function are not "used" until the code is actually run. As
    you "run" the file itself, that binds the names declared at that scope. Identifiers are bound when they are run, overriding any previous binding
    for the same identifier at the same scope. (It's just a new entry or
    update in the "__dir__" map for the appropriate object.) Details beyond
    that are, of course, outside the scope of c.l.c.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Wed Sep 30 19:33:49 2026
    From Newsgroup: comp.lang.c

    On 2026-09-30 15:12, Michael S wrote:
    On Wed, 30 Sep 2026 14:31:40 +0200
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    Or how did these problems look like? - And how do you solve it? - By
    renaming, say, hierarchical index variables 'i' to 'i1', 'i2', etc.?

    There was a member variable in the base class and member variable with
    the same name in derived class.

    Yes, I figured as much so far, I assumed so.

    I fear we could dispute well about (mis-)designs with attributes of the
    same name in hierarchical class definitions, what one wants to model by
    that. (I refer, just for one example, to Barton/Nackman: Scientific and Engineering C++. And add a quick note that polymorphism by inheritance
    in C++ is supported by [virtual] _functions_. And usually there's rules
    to have the attributes hidden and accessed by functions. Some problems
    can be tackled by standards and organizational and/or QA means.)

    The programmer accessed (wrote to) a member of derived when his actual intention was to access the one of base. Then he wondered why the value
    in the base instance is wrong.

    A beginner, I suppose? (Usually if one uses some class he'd be looking
    into the derived classes, and from there upward, if he's unfamiliar
    with it. But as mentioned, the problem here might be the "OO"-design.)

    Since it was just a mistake, a fix was easy - removing the offending
    member from declaration of derived class. But finding the bug was not
    easy.

    Install reviews into your company's design and development processes.
    (Just a suggestion.)

    Janis

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.c on Wed Sep 30 18:14:52 2026
    From Newsgroup: comp.lang.c

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 2026-09-30 15:12, Michael S wrote:
    On Wed, 30 Sep 2026 14:31:40 +0200
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    Or how did these problems look like? - And how do you solve it? - By
    renaming, say, hierarchical index variables 'i' to 'i1', 'i2', etc.?

    There was a member variable in the base class and member variable with
    the same name in derived class.

    Yes, I figured as much so far, I assumed so.

    I fear we could dispute well about (mis-)designs with attributes of the
    same name in hierarchical class definitions, what one wants to model by
    that.

    I've been in the habit (inspired by early Unix C) to always use
    a class-specific prefix for all class member variables (even those
    behind getters/setters). Granted the early C compilers required
    that since MoS were top-level symbol table entries, but it's always
    been a useful convention to prevent inadvertent clashes with the
    subclass members. An example would be struct stat.

    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Johann 'Myrkraverk' Oskarsson@johann@myrkraverk.invalid to comp.lang.c on Thu Oct 1 02:41:18 2026
    From Newsgroup: comp.lang.c

    On 9/30/2026 3:13 PM, Lawrence DrCOOliveiro wrote:
    Or, you know, you could avoid wasting everybodyrCOs time, shut up, and
    use the existing wonderful library of readily available,
    well-documented, standards-compliant open-source routines that already
    do the job so well.

    Dear Lawrence,

    Since you know so much, do you care to enlighten us about the available literature for people who wish to implement their own -- open source or
    not -- wonderful libraries of basic functions? I mean, I have /Hacker's Delight/ by Warren on my shelf, but it can't be the only book dedicated
    to /readily available well documented standards compliant routines/.

    You know as well as I do, that it's all the rage to implement new C lib-
    raries these days, and some are probably being written in Rust as we
    speak.


    So what do you say? Do you have other books to recommend budding C lib-
    rary authors?
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;
    Federated at https://fed.brid.gy/bsky/myrkraverk.bsky.social
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Wed Sep 30 12:42:47 2026
    From Newsgroup: comp.lang.c

    On 9/27/2026 11:04 AM, fir wrote:
    fir pisze:
    you know there are a lacking tiny functions in c-lib
    (by c-lib i mean those standard c includes all know)

    AND if people use many maybe there is a need to standarize it
    byslef? if you need some could be ggood candidates for standarisation
    maybe write it here (i mean whole body of such function)

    we could and should discuss them


    maybe something liek this?


    int mini(int a,int b) { return a<b?a:b; }
    int maxi(int a,int b) { return a>b?a:b; }
    float minf(float a,float b) { return a<b?a:b; }
    float maxf(float a,float b) { return a>b?a:b; }
    int absi(int x) { return x<0?-x:x; }
    float absf(float x) { return x<0?-x:x; }
    float signf(float x) { return x>0?1:x<0?-1:0; }
    int signi(int x) { return x>0?1:x<0?-1:0; }

    //above controversial?

    int clampi(int x,int a,int b) { return x<a?a:x>b?b:x; }
    float clampf(float x,float a,float b) { return x<a?a:x>b?b:x; }
    int betweeni(int x,int a,int b) {-a return x>=a && x<=b; }

    float lerp(float a,float b,float t) { return a+(b-a)*t; }
    float inv_lerp(float a,float b,float x) { return (x-a)/(b-a); }
    float remap(float x,float a,float b,float c,float d) { return c+(x- a)*(d-c)/(b-a); }
    float rad(float x) { return x*PI/180.0f; }
    float deg(float x) { return x*180.0f/PI; }

    //thise above i dont quite use

    float dist2_square(float x1,float y1,float x2,float y2) {-a-a float x=x2- x1,y=y2-y1;-a-a-a-a return x*x+y*y; }
    float dist2(float x1,float y1,float x2,float y2) {-a-a-a return sqrtf(dist2(x1,y1,x2,y2));}
    float len2_square(float x,float y) {-a-a-a return x*x+y*y; }
    float len2(float x,float y) {-a return sqrtf(x*x+y*y);}
    float dot2(float ax,float ay,float bx,float by){-a-a return ax*bx+ay*by;} float cross2(float ax,float ay,float bx,float by){-a-a-a return ax*by-ay*bx;} void-a norm2(float *x,float *y) {-a float d=sqrtf(*x**x+*y**y);-a-a if(d>0) { *x/=d;-a *y/=d; }}
    float dist2_to_line(float px,float py,float ax,float ay,float bx,float by){-a-a-a return fabsf(cross2(bx-ax,by-ay,px-ax,py-ay)) / sqrtf(dist2_square(ax,ay,bx,by));}

    // hare names may be controversial

    the fact is imo though people should generallu decide and use one set of such names imo

    there is also more functions to put here


    Go for say GLSL. Oh wait, that's already a std. HLSL? Another std. For c++:

    https://github.com/g-truc/glm

    Oh wait, it does not need to be std in the language.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Wed Sep 30 22:12:07 2026
    From Newsgroup: comp.lang.c

    On 30/09/2026 17:26, David Brown wrote:
    On 30/09/2026 17:54, bart wrote:

    (However, one feature I have which is out-of-order definitions,
    together with the ability to omit having a main() wrapper around top-
    level executable statement, is very susceptible to such errors. So
    that has been banned on one language and in another is only used for
    throwaway programs.)

    Out-of-order definitions within a scope is susceptible to a lot of
    risks, unless it is quite restricted.-a In particular, I would restrict
    it to constant "things" - constant objects and functions, and perhaps types.-a I would hate to figure out what is going on with "x = 2;"
    followed by "int x = 3;" in the same scope.-a (Maybe you don't allow initialisation in variable definitions?)

    Names can be declared anywhere in a scope, even all at the end.

    That is uncommon for manually written code, but it is highly useful for machine-generated code, when you don't have all the info needed for a declaration until the body of a function has been generated.

    If there is a runtime initialisation for a variable, then that will be
    done at the declaration point. If that declaration is encountered again,
    it will be reinitialised.

    C works the same way, except the name is not in scope until after the declaration.

    This gives the side-effect of allowing two identifiers with the same
    name within the scope:

    int abc=100; // [1]

    int main() {
    printf("%d\n", abc); // abc [1]
    char* abc="200"; // [2]
    printf("%s\n", abc); // abc [2]
    }

    This can give some odd effects: move that second declaration after the
    second printf, or comment it out, and it will go wrong. If it still
    compiles, you now have a bug.

    (The problem I mentioned is this in my systems language:

    proc F(int n) =
    for i in 1..n do print "*" end
    println
    end

    for i in 1..5 do F(i) end

    For-loop indices are auto-declared if no variable of that name is in
    scope. The second 'i' is thus declared to be 'int', at module scope,
    visible everywhere.

    Inside F(), since no local 'i' has been declared, it will use that outer
    'i' and overwrite the caller's 'i' when it runs that loop.

    Python has a similar problem, but it is not as bad since, if F tries to
    modify 'i', it assumes it is a local.)


    Clashes between the same imported name /are/ detected, so that I know
    to do something about it. Another approach would be to silently use
    the first match.


    Noisy errors on clashes are a good idea if there is no clear and
    consistent ordering.

    (I don't know what languages do that other than Python using 'from'
    imports. I don't know enough C++ to try it out via 'using'.)

    I've now tested C++, and with 'namespaces' and 'using', ambiguities are reported by g++.

    (My scheme is more about modules, which also create a namespace; I've
    not attempted C++ modules.)


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Sep 30 22:31:50 2026
    From Newsgroup: comp.lang.c

    On Wed, 30 Sep 2026 13:24:47 +0100, bart wrote:

    The broader point is that pretty much any arithmetic involving
    floats can overflow the range if the magnitudes are large enough (or
    small enough with divide etc).

    The broader, broader point is that if the overflow or underflow occurs
    in intermediate values inside the function that the caller never sees,
    rather than in the final result, that just adds to the mystery and
    frustration that the caller suffers while trying to debug their
    program.

    It may not always be possible to avoid this completely, but there are
    often ways to rework the algorithm to minimize their impact. Doing
    this is worthwhile if it increases the usefulness of the numerics
    library.

    Which is something that experts in numerics make something of a
    specialty.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Thu Oct 1 09:44:06 2026
    From Newsgroup: comp.lang.c

    On 30/09/2026 23:12, bart wrote:
    On 30/09/2026 17:26, David Brown wrote:
    On 30/09/2026 17:54, bart wrote:

    (However, one feature I have which is out-of-order definitions,
    together with the ability to omit having a main() wrapper around top-
    level executable statement, is very susceptible to such errors. So
    that has been banned on one language and in another is only used for
    throwaway programs.)

    Out-of-order definitions within a scope is susceptible to a lot of
    risks, unless it is quite restricted.-a In particular, I would restrict
    it to constant "things" - constant objects and functions, and perhaps
    types.-a I would hate to figure out what is going on with "x = 2;"
    followed by "int x = 3;" in the same scope.-a (Maybe you don't allow
    initialisation in variable definitions?)

    Names can be declared anywhere in a scope, even all at the end.

    That is uncommon for manually written code, but it is highly useful for machine-generated code, when you don't have all the info needed for a declaration until the body of a function has been generated.

    I honestly have no use or sympathy for features like this that are to
    make life easier for machine-generation of code. I cannot imagine that
    it is a major challenge to separate the "create the function" and the
    "write the function to the file" parts, and inject the declarations at
    the start of the written function instead of the end.

    I do realise that you can take shortcuts when it is your private
    language, and the shortcuts save you time and effort in writing your
    tools. But that does not apply to languages for other people.


    If there is a runtime initialisation for a variable, then that will be
    done at the declaration point. If that declaration is encountered again,
    it will be reinitialised.

    So what does this do?

    x = x + 1
    print x
    int x = 100



    C works the same way, except the name is not in scope until after the declaration.

    No - you can't really "reinitialise" anything in C. If you have :

    while (true)
    { // line 0
    printf("Start\n"); // line 1
    int x = 1; // line 2
    printf("X = %i\n", x); // line 3
    } // line 4

    you are /not/ re-initialising "x" each pass through the loop.

    As control flow enters the block in line 0, a new object of type "int"
    starts its lifetime. It is as yet unnamed, uninitialised, and
    unconnected to any scope.

    In line 2, after "int x" we now have a name for this int object, and its
    scope starts. (The scope starts at that point, before the initialiser
    is evaluated and therefore before the declaration is complete. Writing
    "int y = y;" attempts to initialise a new "y" with itself, even if there
    is another "y" declared in an outer scope.) In the rest of line 2, the initialiser is evaluated and assigned to "x" - "initialisation" is the assignment that occurs in connection with the declaration, and has
    additional restrictions that do not apply in normal assignments.

    Line 3 prints the value of "x". Note that while executing the printf
    call, "x" is still within its lifetime, but not within its scope.

    At line 4, the scope of "x" ends at the end of the block. The lifetime
    of "x" also ends as it leaves the block.

    When flow then goes back to the start of the block in line 0, a
    completely new int object is created, and a new variable "x" is bound to
    this and enters scope in line 2.

    At no point is "x" reinitialised - it's a different "x" object for each
    pass of the loop. And the scope of each "x" starts after the "int x"
    bit, before the declaration is complete. (I personally would have
    preferred the scope to start after the initialisation, but C is what it
    is, and there are perhaps good reasons for that choice.)


    It is possible to jump over a declaration, or "re-run" it, using goto.
    This is why lifetime - a run-time property - starts at the beginning of
    the block, while scope - a compile-time property - starts in the
    declaration. In this example, there is only one "x", but it is never
    actually initialised. (If the "x = 42;" line were removed, the first
    call to "foo(x)" would use an unspecified value and be UB.) Instead, it
    is re-assigned each time flow passes through "int x = 12;", just like at
    "x = 42".

    extern void foo(int x);
    void bar(void) {
    goto a;
    b:
    int x = 12;
    foo(x);
    a:
    x = 42;
    foo(x);
    goto b;
    }



    This gives the side-effect of allowing two identifiers with the same
    name within the scope:

    -aint abc=100;-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a-a // [1]

    -aint main() {
    -a-a-a-a printf("%d\n", abc);-a-a-a-a-a-a // abc [1]
    -a-a-a-a char* abc="200";-a-a-a-a-a-a-a-a-a-a // [2]
    -a-a-a-a printf("%s\n", abc);-a-a-a-a-a-a // abc [2]
    -a}


    That is not a side-effect - that is just how languages with scoped
    identifiers work.

    And like most language features, it lets you write more useful correct
    code, and also lets you accidentally write other kinds of incorrect code.

    This can give some odd effects: move that second declaration after the second printf, or comment it out, and it will go wrong. If it still compiles, you now have a bug.

    (The problem I mentioned is this in my systems language:

    -a-a proc F(int n) =
    -a-a-a-a-a-a for i in 1..n do print "*" end
    -a-a-a-a-a-a println
    -a-a end

    -a-a for i in 1..5 do F(i) end

    For-loop indices are auto-declared if no variable of that name is in
    scope. The second 'i' is thus declared to be 'int', at module scope,
    visible everywhere.

    Your problem here, I would say, is inconsistent rules about declarations
    and when they must be explicit or are automatically declared, combined
    with poor choices of scoping rules. If you want to have implicit
    declarations for your "for" loop variables, then make them /always/
    implicit declarations, and always minimal scope.


    Inside F(), since no local 'i' has been declared, it will use that outer
    'i' and overwrite the caller's 'i' when it runs that loop.

    Python has a similar problem, but it is not as bad since, if F tries to modify 'i', it assumes it is a local.)


    Clashes between the same imported name /are/ detected, so that I know
    to do something about it. Another approach would be to silently use
    the first match.


    Noisy errors on clashes are a good idea if there is no clear and
    consistent ordering.

    (I don't know what languages do that other than Python using 'from'
    imports. I don't know enough C++ to try it out via 'using'.)

    I've now tested C++, and with 'namespaces' and 'using', ambiguities are reported by g++.

    (My scheme is more about modules, which also create a namespace; I've
    not attempted C++ modules.)



    I recommend you do not think about C++ modules - they add a layer of complexity that will not help, and they are entirely orthogonal to
    namespaces. (i.e., you don't need modules for namespaces, and modules
    do not implicitly use or declare namespaces.) In particular, you can
    play around with namespaces, using, etc., on godbolt.org, but you can't practice modules there in any real way, since you only have one file.


    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Thu Oct 1 08:49:18 2026
    From Newsgroup: comp.lang.c

    On Wed, 30 Sep 2026 10:52:59 +0100, bart wrote:

    On 30/09/2026 03:09, James Kuyper wrote:

    On Tue, 29 Sep 2026 14:36:34 +0100, bart wrote:

    What exactly is incorrect about the naive method? That it
    stops > working at a lower magnitude than hypot()?

    It stops working at a MUCH lower magnitude. The naive
    implementation overflows if either argument > sqrt(DBL_MAX).

    Well, so what? You can say that about lots of different expressions
    and functions!

    But not the na|>ve one offered by the original poster.

    It takes someone with decent numeric skills to design something
    better. And we have that. So we donrCOt need to rely on random code
    posted online by novice programmers.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Thu Oct 1 08:52:55 2026
    From Newsgroup: comp.lang.c

    On Wed, 30 Sep 2026 01:00:22 -0700, Chris M. Thomasson wrote:

    Here is a more self-contained version of my generator. It asks you
    how many vertices to enter. Builds CTTEST.BAS, then you can just
    EXEC CTTEST.BAS to run it. Here is my code. Just for fun. The
    generated code draws a bunch of polys using the table LT.

    ThatrCOs one way to create dynamic data structures from a language
    which, on the face of it, has no built-in support for that.

    Turing-equivalence, after all, is an entirely separate issue from
    whether the language is actually convenient to use. ThatrCOs the
    difference between mathematicians and computer scientists, as to which
    of the two they care more about.
    --- Synchronet 3.22a-Linux NewsLink 1.2