discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

is_nan()

RD
Revar Desmera
Fri, Feb 7, 2020 8:25 AM

I'm sure this has come up before, but in a cursory check I didn't see anyone else post an actual solution.

The FP value nan is handled in OpenSCAD in a very awkward manner. First-off, there's no constants for nan or inf, so lets work around that:

NAN = acos(2);
INF = 1/0;

Secondly, the comparators for nan, while arguably true from an academic point of view, are almost completely useless from a programming perspective:

  • is_num(NAN) returns false. (Even though nan is of the same type as inf and 0.)
  • NAN == NAN returns false.
  • NAN != NAN returns true.

Combined, these really make it very ugly to tell if a value is nan.  The obvious tests are all useless:

x = foo();
if (x==NAN) echo("This branch is NEVER executed for any value or type of x.");
if (x!=NAN) echo("This branch is executed for ALL values of x, no matter the type.");

As far as I can tell, the only way to detect NaN correctly is a complex construct like this:

function is_nan(x) =
	!is_num(x) && !is_undef(x) && !is_string(x) &&
	!is_list(x) && !(x<=INF) && is_undef(x[0]);

The !(x<=INF) test disallows INF, -INF, and booleans. The is_undef(x[0]) shows that x is not a range like [0:10].

  • Revar
I'm sure this has come up before, but in a cursory check I didn't see anyone else post an actual solution. The FP value `nan` is handled in OpenSCAD in a very awkward manner. First-off, there's no constants for nan or inf, so lets work around that: NAN = acos(2); INF = 1/0; Secondly, the comparators for nan, while arguably true from an academic point of view, are almost completely useless from a programming perspective: - `is_num(NAN)` returns false. (Even though nan is of the same type as inf and 0.) - `NAN == NAN` returns false. - `NAN != NAN` returns true. Combined, these really make it very ugly to tell if a value is nan. The obvious tests are all useless: x = foo(); if (x==NAN) echo("This branch is NEVER executed for any value or type of x."); if (x!=NAN) echo("This branch is executed for ALL values of x, no matter the type."); As far as I can tell, the only way to detect NaN correctly is a complex construct like this: function is_nan(x) = !is_num(x) && !is_undef(x) && !is_string(x) && !is_list(x) && !(x<=INF) && is_undef(x[0]); The !(x<=INF) test disallows INF, -INF, and booleans. The is_undef(x[0]) shows that x is not a range like [0:10]. - Revar
W
Whosawhatsis
Fri, Feb 7, 2020 8:31 AM

function is_nan(x) = (x != x) ? true : false;

On February 7, 2020 at 00:25:59, Revar Desmera (revarbat@gmail.com) wrote:

I'm sure this has come up before, but in a cursory check I didn't see
anyone else post an actual solution.

The FP value nan is handled in OpenSCAD in a very awkward manner.
First-off, there's no constants for nan or inf, so lets work around that:

NAN = acos(2);
INF = 1/0;

Secondly, the comparators for nan, while arguably true from an academic
point of view, are almost completely useless from a programming
perspective:

  • is_num(NAN) returns false. (Even though nan is of the same type as inf
    and 0.)
  • NAN == NAN returns false.
  • NAN != NAN returns true.

Combined, these really make it very ugly to tell if a value is nan. The
obvious tests are all useless:

x = foo();
if (x==NAN) echo("This branch is NEVER executed for any value or type of
x.");
if (x!=NAN) echo("This branch is executed for ALL values of x, no matter
the type.");

As far as I can tell, the only way to detect NaN correctly is a complex
construct like this:

function is_nan(x) =
!is_num(x) && !is_undef(x) && !is_string(x) &&
!is_list(x) && !(x<=INF) && is_undef(x[0]);

The !(x<=INF) test disallows INF, -INF, and booleans. The is_undef(x[0])
shows that x is not a range like [0:10].

  • Revar

OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

function is_nan(x) = (x != x) ? true : false; On February 7, 2020 at 00:25:59, Revar Desmera (revarbat@gmail.com) wrote: I'm sure this has come up before, but in a cursory check I didn't see anyone else post an actual solution. The FP value `nan` is handled in OpenSCAD in a very awkward manner. First-off, there's no constants for nan or inf, so lets work around that: NAN = acos(2); INF = 1/0; Secondly, the comparators for nan, while arguably true from an academic point of view, are almost completely useless from a programming perspective: - `is_num(NAN)` returns false. (Even though nan is of the same type as inf and 0.) - `NAN == NAN` returns false. - `NAN != NAN` returns true. Combined, these really make it very ugly to tell if a value is nan. The obvious tests are all useless: x = foo(); if (x==NAN) echo("This branch is NEVER executed for any value or type of x."); if (x!=NAN) echo("This branch is executed for ALL values of x, no matter the type."); As far as I can tell, the only way to detect NaN correctly is a complex construct like this: function is_nan(x) = !is_num(x) && !is_undef(x) && !is_string(x) && !is_list(x) && !(x<=INF) && is_undef(x[0]); The !(x<=INF) test disallows INF, -INF, and booleans. The is_undef(x[0]) shows that x is not a range like [0:10]. - Revar _______________________________________________ OpenSCAD mailing list Discuss@lists.openscad.org http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
RD
Revar Desmera
Fri, Feb 7, 2020 10:02 AM

Huh.  Even shorter:

function is_nan(x) = x!=x;

That is somehow both elegant in its simplicity and horribly twisted in its logic.

  • Revar

On Feb 7, 2020, at 12:31 AM, Whosawhatsis whosawhatsis@gmail.com wrote:

function is_nan(x) = (x != x) ? true : false;

On February 7, 2020 at 00:25:59, Revar Desmera (revarbat@gmail.com mailto:revarbat@gmail.com) wrote:

I'm sure this has come up before, but in a cursory check I didn't see anyone else post an actual solution.

The FP value nan is handled in OpenSCAD in a very awkward manner. First-off, there's no constants for nan or inf, so lets work around that:

NAN = acos(2);
INF = 1/0;

Secondly, the comparators for nan, while arguably true from an academic point of view, are almost completely useless from a programming perspective:

  • is_num(NAN) returns false. (Even though nan is of the same type as inf and 0.)
  • NAN == NAN returns false.
  • NAN != NAN returns true.

Combined, these really make it very ugly to tell if a value is nan. The obvious tests are all useless:

x = foo();
if (x==NAN) echo("This branch is NEVER executed for any value or type of x.");
if (x!=NAN) echo("This branch is executed for ALL values of x, no matter the type.");

As far as I can tell, the only way to detect NaN correctly is a complex construct like this:

function is_nan(x) =
!is_num(x) && !is_undef(x) && !is_string(x) &&
!is_list(x) && !(x<=INF) && is_undef(x[0]);

The !(x<=INF) test disallows INF, -INF, and booleans. The is_undef(x[0]) shows that x is not a range like [0:10].

  • Revar

OpenSCAD mailing list
Discuss@lists.openscad.org mailto:Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Huh. Even shorter: function is_nan(x) = x!=x; That is somehow both elegant in its simplicity and horribly twisted in its logic. - Revar > On Feb 7, 2020, at 12:31 AM, Whosawhatsis <whosawhatsis@gmail.com> wrote: > > function is_nan(x) = (x != x) ? true : false; > > On February 7, 2020 at 00:25:59, Revar Desmera (revarbat@gmail.com <mailto:revarbat@gmail.com>) wrote: > >> I'm sure this has come up before, but in a cursory check I didn't see anyone else post an actual solution. >> >> The FP value `nan` is handled in OpenSCAD in a very awkward manner. First-off, there's no constants for nan or inf, so lets work around that: >> >> NAN = acos(2); >> INF = 1/0; >> >> Secondly, the comparators for nan, while arguably true from an academic point of view, are almost completely useless from a programming perspective: >> >> - `is_num(NAN)` returns false. (Even though nan is of the same type as inf and 0.) >> - `NAN == NAN` returns false. >> - `NAN != NAN` returns true. >> >> Combined, these really make it very ugly to tell if a value is nan. The obvious tests are all useless: >> >> x = foo(); >> if (x==NAN) echo("This branch is NEVER executed for any value or type of x."); >> if (x!=NAN) echo("This branch is executed for ALL values of x, no matter the type."); >> >> As far as I can tell, the only way to detect NaN correctly is a complex construct like this: >> >> function is_nan(x) = >> !is_num(x) && !is_undef(x) && !is_string(x) && >> !is_list(x) && !(x<=INF) && is_undef(x[0]); >> >> The !(x<=INF) test disallows INF, -INF, and booleans. The is_undef(x[0]) shows that x is not a range like [0:10]. >> >> - Revar >> >> >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@lists.openscad.org <mailto:Discuss@lists.openscad.org> >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org <http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org>
TP
Torsten Paul
Fri, Feb 7, 2020 8:00 PM

On 07.02.20 11:02, Revar Desmera wrote:

function is_nan(x) = x!=x;
That is somehow both elegant in its simplicity and horribly
twisted in its logic.

Also nobody will claim any responsibility if it breaks at
some point.

If it makes sense to have that check, it would probably be
better to actually implemented it in the core like the other
test functions.

The missing tokens are indeed a problem as that is one case
where we can export files as CSG that can't be imported back.

nan = 0/0;
inf = 1/0;
ninf = -1/0;
echo(inf, ninf, nan);

Just to highlight the point it's not an OpenSCAD invention:

$ python3
Python 3.7.6 (default, Jan 19 2020, 22:34:52)
[GCC 9.2.1 20200117] on linux
Type "help", "copyright", "credits" or "license" for more information.

import math
nan = math.nan
nan == nan

False

nan != nan

True

ciao,
Torsten.

On 07.02.20 11:02, Revar Desmera wrote: > function is_nan(x) = x!=x; > That is somehow both elegant in its simplicity and horribly > twisted in its logic. Also nobody will claim any responsibility if it breaks at some point. If it makes sense to have that check, it would probably be better to actually implemented it in the core like the other test functions. The missing tokens are indeed a problem as that is one case where we can export files as CSG that can't be imported back. nan = 0/0; inf = 1/0; ninf = -1/0; echo(inf, ninf, nan); Just to highlight the point it's not an OpenSCAD invention: $ python3 Python 3.7.6 (default, Jan 19 2020, 22:34:52) [GCC 9.2.1 20200117] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import math >>> nan = math.nan >>> nan == nan False >>> nan != nan True >>> ciao, Torsten.
AC
A. Craig West
Fri, Feb 7, 2020 10:01 PM

Nan is pretty much defined to not be equal to itself, part of the floating
point spec

On Fri, 7 Feb 2020, 15:01 Torsten Paul, Torsten.Paul@gmx.de wrote:

On 07.02.20 11:02, Revar Desmera wrote:

function is_nan(x) = x!=x;
That is somehow both elegant in its simplicity and horribly
twisted in its logic.

Also nobody will claim any responsibility if it breaks at
some point.

If it makes sense to have that check, it would probably be
better to actually implemented it in the core like the other
test functions.

The missing tokens are indeed a problem as that is one case
where we can export files as CSG that can't be imported back.

nan = 0/0;
inf = 1/0;
ninf = -1/0;
echo(inf, ninf, nan);

Just to highlight the point it's not an OpenSCAD invention:

$ python3
Python 3.7.6 (default, Jan 19 2020, 22:34:52)
[GCC 9.2.1 20200117] on linux
Type "help", "copyright", "credits" or "license" for more information.

import math
nan = math.nan
nan == nan

False

nan != nan

True

Nan is pretty much defined to not be equal to itself, part of the floating point spec On Fri, 7 Feb 2020, 15:01 Torsten Paul, <Torsten.Paul@gmx.de> wrote: > On 07.02.20 11:02, Revar Desmera wrote: > > function is_nan(x) = x!=x; > > That is somehow both elegant in its simplicity and horribly > > twisted in its logic. > > Also nobody will claim any responsibility if it breaks at > some point. > > If it makes sense to have that check, it would probably be > better to actually implemented it in the core like the other > test functions. > > The missing tokens are indeed a problem as that is one case > where we can export files as CSG that can't be imported back. > > nan = 0/0; > inf = 1/0; > ninf = -1/0; > echo(inf, ninf, nan); > > Just to highlight the point it's not an OpenSCAD invention: > > $ python3 > Python 3.7.6 (default, Jan 19 2020, 22:34:52) > [GCC 9.2.1 20200117] on linux > Type "help", "copyright", "credits" or "license" for more information. > >>> import math > >>> nan = math.nan > >>> nan == nan > False > >>> nan != nan > True > >>> > > ciao, > Torsten. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
DM
Doug Moen
Fri, Feb 7, 2020 11:28 PM

The IEEE floating point standard provides programming languages with two different options
when evaluating 0/0: either it raises an exception, or it returns the NaN value.

Once you have a NaN value x, then x!=x must return true, according to IEEE.

In Python, 0.0/0.0 raises an exception, it doesn't return NaN.
In OpenSCAD, 0/0 returns NaN instead of raising an exception.
Both languages are compatible with the IEEE standard in this circumstance.

If you prefer your programming language to report an error when you have performed
an illegal operation, rather than silently returning Nan or undef, then you probably
want the Python semantics of 0/0 raising an exception.

In my own 3D modelling language (Curv), arithmetic operations always report an error
rather than return NaN. Since there's no way to generate a NaN, I don't need an is_nan()
function, and it is guaranteed that x==x is always true and x!=x is always false.
The only time I've actually seen this error reported was due to a bug in my program, that
would otherwise have resulted in exporting an invalid STL file if the bug hadn't been fixed.

My opinion is that disabling floating point exceptions and returning NaN for invalid arithmetic
operations is something that should only be attempted by numerical analysts who know what
they are doing. The semantics of NaN are too confusing, and propagating NaN values through
an OpenSCAD program will probably result in bad geometry. I don't think that 0/0 should
return NaN by default in a programming language that isn't targeted at high performance
numerical analysis. Python gets this right.

Doug Moen.

On Fri, Feb 7, 2020, at 8:00 PM, Torsten Paul wrote:

On 07.02.20 11:02, Revar Desmera wrote:

function is_nan(x) = x!=x;
That is somehow both elegant in its simplicity and horribly
twisted in its logic.

Also nobody will claim any responsibility if it breaks at
some point.

If it makes sense to have that check, it would probably be
better to actually implemented it in the core like the other
test functions.

The missing tokens are indeed a problem as that is one case
where we can export files as CSG that can't be imported back.

nan = 0/0;
inf = 1/0;
ninf = -1/0;
echo(inf, ninf, nan);

Just to highlight the point it's not an OpenSCAD invention:

$ python3
Python 3.7.6 (default, Jan 19 2020, 22:34:52)
[GCC 9.2.1 20200117] on linux
Type "help", "copyright", "credits" or "license" for more information.

import math
nan = math.nan
nan == nan

False

nan != nan

True

The IEEE floating point standard provides programming languages with two different options when evaluating 0/0: either it raises an exception, or it returns the NaN value. Once you have a NaN value x, then x!=x must return true, according to IEEE. In Python, 0.0/0.0 raises an exception, it doesn't return NaN. In OpenSCAD, 0/0 returns NaN instead of raising an exception. Both languages are compatible with the IEEE standard in this circumstance. If you prefer your programming language to report an error when you have performed an illegal operation, rather than silently returning Nan or undef, then you probably want the Python semantics of 0/0 raising an exception. In my own 3D modelling language (Curv), arithmetic operations always report an error rather than return NaN. Since there's no way to generate a NaN, I don't need an is_nan() function, and it is guaranteed that x==x is always true and x!=x is always false. The only time I've actually seen this error reported was due to a bug in my program, that would otherwise have resulted in exporting an invalid STL file if the bug hadn't been fixed. My opinion is that disabling floating point exceptions and returning NaN for invalid arithmetic operations is something that should only be attempted by numerical analysts who know what they are doing. The semantics of NaN are too confusing, and propagating NaN values through an OpenSCAD program will probably result in bad geometry. I don't think that 0/0 should return NaN by default in a programming language that isn't targeted at high performance numerical analysis. Python gets this right. Doug Moen. On Fri, Feb 7, 2020, at 8:00 PM, Torsten Paul wrote: > On 07.02.20 11:02, Revar Desmera wrote: > > function is_nan(x) = x!=x; > > That is somehow both elegant in its simplicity and horribly > > twisted in its logic. > > Also nobody will claim any responsibility if it breaks at > some point. > > If it makes sense to have that check, it would probably be > better to actually implemented it in the core like the other > test functions. > > The missing tokens are indeed a problem as that is one case > where we can export files as CSG that can't be imported back. > > nan = 0/0; > inf = 1/0; > ninf = -1/0; > echo(inf, ninf, nan); > > Just to highlight the point it's not an OpenSCAD invention: > > $ python3 > Python 3.7.6 (default, Jan 19 2020, 22:34:52) > [GCC 9.2.1 20200117] on linux > Type "help", "copyright", "credits" or "license" for more information. > >>> import math > >>> nan = math.nan > >>> nan == nan > False > >>> nan != nan > True > >>> > > ciao, > Torsten. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
RD
Revar Desmera
Sat, Feb 8, 2020 12:54 AM

Yeah, I'd like to see a proper is_nan(x) builtin.  And an is_range(x) as well.

IEEE754 is correct to specify that nan!=nan, as that is what you want when comparing results from two calculations.
Most languages, however, also provide ways to test for nan.

$ python3

import math
nan = math.nan
nan is math.nan

True

math.isnan(nan)

True

Even C/C++ has isnan(x).

I'm fine with nan!=nan, so long as there exists a clean way to test for it.  We need is_nan().

  • Revar

On Feb 7, 2020, at 12:00 PM, Torsten Paul Torsten.Paul@gmx.de wrote:

On 07.02.20 11:02, Revar Desmera wrote:

function is_nan(x) = x!=x;
That is somehow both elegant in its simplicity and horribly
twisted in its logic.

Also nobody will claim any responsibility if it breaks at
some point.

If it makes sense to have that check, it would probably be
better to actually implemented it in the core like the other
test functions.

The missing tokens are indeed a problem as that is one case
where we can export files as CSG that can't be imported back.

nan = 0/0;
inf = 1/0;
ninf = -1/0;
echo(inf, ninf, nan);

Just to highlight the point it's not an OpenSCAD invention:

$ python3
Python 3.7.6 (default, Jan 19 2020, 22:34:52)
[GCC 9.2.1 20200117] on linux
Type "help", "copyright", "credits" or "license" for more information.

import math
nan = math.nan
nan == nan

False

nan != nan

True

Yeah, I'd like to see a proper is_nan(x) builtin. And an is_range(x) as well. IEEE754 is correct to specify that nan!=nan, as that is what you want when comparing results from two calculations. Most languages, however, also provide ways to test for nan. $ python3 >>> import math >>> nan = math.nan >>> nan is math.nan True >>> math.isnan(nan) True Even C/C++ has isnan(x). I'm fine with nan!=nan, so long as there exists a clean way to test for it. We need is_nan(). - Revar > On Feb 7, 2020, at 12:00 PM, Torsten Paul <Torsten.Paul@gmx.de> wrote: > > On 07.02.20 11:02, Revar Desmera wrote: >> function is_nan(x) = x!=x; >> That is somehow both elegant in its simplicity and horribly >> twisted in its logic. > > Also nobody will claim any responsibility if it breaks at > some point. > > If it makes sense to have that check, it would probably be > better to actually implemented it in the core like the other > test functions. > > The missing tokens are indeed a problem as that is one case > where we can export files as CSG that can't be imported back. > > nan = 0/0; > inf = 1/0; > ninf = -1/0; > echo(inf, ninf, nan); > > Just to highlight the point it's not an OpenSCAD invention: > > $ python3 > Python 3.7.6 (default, Jan 19 2020, 22:34:52) > [GCC 9.2.1 20200117] on linux > Type "help", "copyright", "credits" or "license" for more information. > >>> import math > >>> nan = math.nan > >>> nan == nan > False > >>> nan != nan > True > >>> > > ciao, > Torsten. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
HL
Hans L
Sat, Feb 8, 2020 11:40 AM

Here's an is_range function I came up with a while ago:
is_range = function (x) !is_list(x) && !is_string(x) && !is_undef(x[0]);

It works because you can access start,step,end as the first 3 "elements",
but its not a list.

On Fri, Feb 7, 2020 at 6:55 PM Revar Desmera revarbat@gmail.com wrote:

Yeah, I'd like to see a proper is_nan(x) builtin.  And an is_range(x) as
well.

IEEE754 is correct to specify that nan!=nan, as that is what you want when
comparing results from two calculations.
Most languages, however, also provide ways to test for nan.

$ python3

import math
nan = math.nan
nan is math.nan

True

math.isnan(nan)

True

Even C/C++ has isnan(x).

I'm fine with nan!=nan, so long as there exists a clean way to test for
it.  We need is_nan().

  • Revar

On Feb 7, 2020, at 12:00 PM, Torsten Paul Torsten.Paul@gmx.de wrote:

On 07.02.20 11:02, Revar Desmera wrote:

function is_nan(x) = x!=x;
That is somehow both elegant in its simplicity and horribly
twisted in its logic.

Also nobody will claim any responsibility if it breaks at
some point.

If it makes sense to have that check, it would probably be
better to actually implemented it in the core like the other
test functions.

The missing tokens are indeed a problem as that is one case
where we can export files as CSG that can't be imported back.

nan = 0/0;
inf = 1/0;
ninf = -1/0;
echo(inf, ninf, nan);

Just to highlight the point it's not an OpenSCAD invention:

$ python3
Python 3.7.6 (default, Jan 19 2020, 22:34:52)
[GCC 9.2.1 20200117] on linux
Type "help", "copyright", "credits" or "license" for more information.

import math
nan = math.nan
nan == nan

False

nan != nan

True

Here's an is_range function I came up with a while ago: is_range = function (x) !is_list(x) && !is_string(x) && !is_undef(x[0]); It works because you can access start,step,end as the first 3 "elements", but its not a list. On Fri, Feb 7, 2020 at 6:55 PM Revar Desmera <revarbat@gmail.com> wrote: > Yeah, I'd like to see a proper is_nan(x) builtin. And an is_range(x) as > well. > > IEEE754 is correct to specify that nan!=nan, as that is what you want when > comparing results from two calculations. > Most languages, however, also provide ways to test for nan. > > $ python3 > >>> import math > >>> nan = math.nan > >>> nan is math.nan > True > >>> math.isnan(nan) > True > > Even C/C++ has isnan(x). > > I'm fine with nan!=nan, so long as there exists a clean way to test for > it. We need is_nan(). > > - Revar > > > > On Feb 7, 2020, at 12:00 PM, Torsten Paul <Torsten.Paul@gmx.de> wrote: > > > > On 07.02.20 11:02, Revar Desmera wrote: > >> function is_nan(x) = x!=x; > >> That is somehow both elegant in its simplicity and horribly > >> twisted in its logic. > > > > Also nobody will claim any responsibility if it breaks at > > some point. > > > > If it makes sense to have that check, it would probably be > > better to actually implemented it in the core like the other > > test functions. > > > > The missing tokens are indeed a problem as that is one case > > where we can export files as CSG that can't be imported back. > > > > nan = 0/0; > > inf = 1/0; > > ninf = -1/0; > > echo(inf, ninf, nan); > > > > Just to highlight the point it's not an OpenSCAD invention: > > > > $ python3 > > Python 3.7.6 (default, Jan 19 2020, 22:34:52) > > [GCC 9.2.1 20200117] on linux > > Type "help", "copyright", "credits" or "license" for more information. > > >>> import math > > >>> nan = math.nan > > >>> nan == nan > > False > > >>> nan != nan > > True > > >>> > > > > ciao, > > Torsten. > > > > _______________________________________________ > > OpenSCAD mailing list > > Discuss@lists.openscad.org > > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >