omdl  v0.6.1
OpenSCAD Mechanical Design Library
datatypes_identify_scalar.scad
Go to the documentation of this file.
1 //! Scalar data type identification.
2 /***************************************************************************//**
3  \file datatypes_identify_scalar.scad
4  \author Roy Allen Sutton
5  \date 2015-2017
6 
7  \copyright
8 
9  This file is part of [omdl] (https://github.com/royasutton/omdl),
10  an OpenSCAD mechanical design library.
11 
12  The \em omdl is free software; you can redistribute it and/or modify
13  it under the terms of the [GNU Lesser General Public License]
14  (http://www.gnu.org/licenses/lgpl.html) as published by the Free
15  Software Foundation; either version 2.1 of the License, or (at
16  your option) any later version.
17 
18  The \em omdl is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  Lesser General Public License for more details.
22 
23  You should have received a copy of the GNU Lesser General Public
24  License along with the \em omdl; if not, write to the Free Software
25  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26  02110-1301, USA; or see <http://www.gnu.org/licenses/>.
27 
28 *******************************************************************************/
29 
30 //----------------------------------------------------------------------------//
31 /***************************************************************************//**
32  \page tv_datatypes_identify_scalar Scalar
33  \li \subpage tv_datatypes_identify_scalar_s
34  \li \subpage tv_datatypes_identify_scalar_r
35 
36  \page tv_datatypes_identify_scalar_s Script
37  \dontinclude datatypes_identify_scalar_validate.scad
38  \skip include
39  \until end-of-tests
40  \page tv_datatypes_identify_scalar_r Results
41  \include datatypes_identify_scalar_validate.log
42 *******************************************************************************/
43 //----------------------------------------------------------------------------//
44 
45 //----------------------------------------------------------------------------//
46 /***************************************************************************//**
47  \addtogroup datatypes_identify
48  @{
49 
50  \defgroup datatypes_identify_scalar Scalars
51  \brief Scalar data type identification.
52 
53  \details
54 
55  See validation \ref tv_datatypes_identify_scalar_r "results".
56  @{
57 *******************************************************************************/
58 //----------------------------------------------------------------------------//
59 
60 //! Test if a value is defined.
61 /***************************************************************************//**
62  \param v <value> A value.
63 
64  \returns <boolean> \b true when the value is defined
65  and \b false otherwise.
66 *******************************************************************************/
67 function is_defined
68 (
69  v
70 ) = (v == undef) ? false
71  : true;
72 
73 //! Test if a value is not defined.
74 /***************************************************************************//**
75  \param v <value> A value.
76 
77  \returns <boolean> \b true when the value is not defined
78  and \b false otherwise.
79 *******************************************************************************/
80 function not_defined
81 (
82  v
83 ) = (v == undef) ? true
84  : false;
85 
86 //! Test if a numerical value is invalid.
87 /***************************************************************************//**
88  \param v <value> A numerical value.
89 
90  \returns <boolean> \b true when the value is determined to be
91  \b nan (Not A Number) and \b false otherwise.
92 *******************************************************************************/
93 function is_nan( v ) = ( v != v );
94 
95 //! Test if a numerical value is infinite.
96 /***************************************************************************//**
97  \param v <value> A numerical value.
98 
99  \returns <boolean> \b true when the value is determined to be
100  \b inf (greater than the largest representable number)
101  and \b false otherwise.
102 *******************************************************************************/
103 function is_inf( v ) = ( v == (number_max * number_max) );
104 
105 //! Test if a value is a single non-iterable value.
106 /***************************************************************************//**
107  \param v <value> A value.
108 
109  \returns <boolean> \b true when the value is a single non-iterable value
110  and \b false otherwise.
111 
112  \details
113 
114  data type | defined
115  :-------------:|:-----------------:
116  number(s) | \b true
117  boolean | \b true
118  string | \b false
119  list | \b false
120  range | not defined
121  \b undef | \b true
122  \b inf | \b true
123  \b nan | \b true
124 *******************************************************************************/
125 function is_scalar( v ) = (len(v) == undef);
126 
127 //! Test if a value has multiple parts and is iterable.
128 /***************************************************************************//**
129  \param v <value> A value.
130 
131  \returns <boolean> \b true when the value is an iterable multi-part value
132  and \b false otherwise.
133 
134  \details
135 
136  data type | defined
137  :-------------:|:-----------------:
138  number(s) | \b false
139  boolean | \b false
140  string | \b true
141  list | \b true
142  range | not defined
143  \b undef | \b false
144  \b inf | \b false
145  \b nan | \b false
146 *******************************************************************************/
147 function is_iterable( v ) = (len(v) != undef);
148 
149 //! Test if an iterable value is empty.
150 /***************************************************************************//**
151  \param v <value> An iterable value.
152 
153  \returns <boolean> \b true when the iterable value has zero elements
154  and \b false otherwise.
155 *******************************************************************************/
156 function is_empty( v ) = (len(v) == 0);
157 
158 //! Test if a value is a number.
159 /***************************************************************************//**
160  \param v <value> A value.
161 
162  \returns <boolean> \b true when the value is a number
163  and \b false otherwise.
164 
165  \note Returns \b true for \b inf and \b nan values.
166 *******************************************************************************/
167 function is_number( v ) = is_defined(v % 1);
168 
169 //! Test if a value is an integer.
170 /***************************************************************************//**
171  \param v <value> A value.
172 
173  \returns <boolean> \b true when the value is an integer
174  and \b false otherwise.
175 *******************************************************************************/
176 function is_integer
177 (
178  v
179 ) = not_defined(v) ? false
180  : ((v % 1) == 0);
181 
182 //! Test if a value is a decimal.
183 /***************************************************************************//**
184  \param v <value> A value.
185 
186  \returns <boolean> \b true when the value is a decimal
187  and \b false otherwise.
188 *******************************************************************************/
189 function is_decimal( v ) = ((v % 1) > 0);
190 
191 //! Test if a value is a predefined boolean constant.
192 /***************************************************************************//**
193  \param v <value> A value.
194 
195  \returns <boolean> \b true when the value is one of the predefined
196  boolean constants <tt>[true|false]</tt> and \b false otherwise.
197 *******************************************************************************/
198 function is_boolean
199 (
200  v
201 ) = is_string(v) ? false
202  : (str(v) == "true") ? true
203  : (str(v) == "false") ? true
204  : false;
205 
206 //! Test if a value is a string.
207 /***************************************************************************//**
208  \param v <value> A value.
209 
210  \returns <boolean> \b true when the value is a string
211  and \b false otherwise.
212 *******************************************************************************/
213 function is_string( v ) = (str(v) == v);
214 
215 //! Test if a value is an iterable list of values.
216 /***************************************************************************//**
217  \param v <value> A value.
218 
219  \returns <boolean> \b true when the value is a list
220  and \b false otherwise.
221 *******************************************************************************/
222 function is_list( v ) = is_iterable(v) && !is_string(v);
223 
224 //! Test if a value is a range definition.
225 /***************************************************************************//**
226  \param v <value> A value.
227 
228  \returns <boolean> \b true when the value is a range definition
229  and \b false otherwise.
230 
231  \details
232 
233  \internal
234  Currently a range is determined to be that which does not fit in any
235  other value category. This is likely to fail as OpenSCAD matures.
236  This exclusion test should be replaced by a suitable inclusion test
237  when possible.
238  \endinternal
239 *******************************************************************************/
240 function is_range
241 (
242  v
243 ) = is_defined(v) &&
244  !is_iterable(v) &&
245  !is_boolean(v) &&
246  !is_integer(v) &&
247  !is_decimal(v) &&
248  !is_nan(v) &&
249  !is_inf(v);
250 
251 //! Test if a numerical value is even.
252 /***************************************************************************//**
253  \param v <value> A numerical value.
254 
255  \returns <boolean> \b true when the value is determined to be \e even
256  and \b false otherwise (The value may be positive or negative).
257 *******************************************************************************/
258 function is_even
259 (
260  v
261 ) = !is_integer(v) ? false
262  : ((v % 2) == 0);
263 
264 //! Test if a numerical value is odd.
265 /***************************************************************************//**
266  \param v <value> A numerical value.
267 
268  \returns <boolean> \b true when the value is determined to be \e odd
269  and \b false otherwise (The value may be positive or negative).
270 *******************************************************************************/
271 function is_odd
272 (
273  v
274 ) = !is_integer(v) ? false
275  : ((v % 2) != 0);
276 
277 //! Test if a numerical value is between an upper and lower bounds.
278 /***************************************************************************//**
279  \param v <number> A numerical value.
280  \param l <number> The minimum value.
281  \param u <number> The maximum value.
282 
283  \returns <boolean> \b true when the value is between the upper and
284  lower bounds and \b false otherwise.
285 *******************************************************************************/
286 function is_between
287 (
288  v,
289  l,
290  u
291 ) = ((v >= l) && (v <=u));
292 
293 //! @}
294 //! @}
295 
296 //----------------------------------------------------------------------------//
297 // openscad-amu auxiliary scripts
298 //----------------------------------------------------------------------------//
299 
300 /*
301 BEGIN_SCOPE validate;
302  BEGIN_OPENSCAD;
303  include <console.scad>;
304  include <datatypes/datatypes-base.scad>;
305  include <datatypes/datatypes_table.scad>;
306  include <validation.scad>;
307 
308  show_passing = true; // show passing tests
309  show_skipped = true; // show skipped tests
310 
311  echo( str("OpenSCAD Version ", version()) );
312 
313  // test-values columns
314  test_c =
315  [
316  ["id", "identifier"],
317  ["td", "description"],
318  ["tv", "test value"]
319  ];
320 
321  // test-values rows
322  test_r =
323  [
324  ["t01", "The undefined value", undef],
325  ["t02", "An odd integer", 1],
326  ["t03", "An small even integer", 10],
327  ["t04", "A large integer", 100000000],
328  ["t05", "A small decimal (epsilon)", aeps],
329  ["t06", "The max number", number_max],
330  ["t07", "The min number", number_min],
331  ["t08", "The max number^2", number_max * number_max],
332  ["t09", "The invalid number nan", 0 / 0],
333  ["t10", "The boolean true", true],
334  ["t11", "The boolean false", false],
335  ["t12", "A character string", "a"],
336  ["t13", "A string", "This is a longer string"],
337  ["t14", "The empty string", empty_str],
338  ["t15", "The empty list", empty_lst],
339  ["t16", "A 1-tuple list of undef", [undef]],
340  ["t17", "A 1-tuple list", [10]],
341  ["t18", "A 3-tuple list", [1, 2, 3]],
342  ["t19", "A list of lists", [[1,2,3], [4,5,6], [7,8,9]]],
343  ["t20", "A shorthand range", [0:9]],
344  ["t21", "A range", [0:0.5:9]]
345  ];
346 
347  test_ids = get_table_ridl( test_r );
348 
349  // expected columns: ("id" + one column for each test)
350  good_c = pmerge([concat("id", test_ids), concat("identifier", test_ids)]);
351 
352  // expected rows: ("golden" test results), use 's' to skip test
353  t = true; // shortcuts
354  f = false;
355  u = undef;
356  s = -1; // skip test
357 
358  good_r =
359  [ // function 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21
360  ["is_defined", f, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t],
361  ["not_defined", t, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f],
362  ["is_nan", f, f, f, f, f, f, f, f, t, f, f, f, f, f, f, f, f, f, f, f, f],
363  ["is_inf", f, f, f, f, f, f, f, t, f, f, f, f, f, f, f, f, f, f, f, f, f],
364  ["is_scalar", t, t, t, t, t, t, t, t, t, t, t, f, f, f, f, f, f, f, f, s, s],
365  ["is_iterable", f, f, f, f, f, f, f, f, f, f, f, t, t, t, t, t, t, t, t, s, s],
366  ["is_empty", f, f, f, f, f, f, f, f, f, f, f, f, f, t, t, f, f, f, f, f, f],
367  ["is_number", f, t, t, t, t, t, t, t, t, f, f, f, f, f, f, f, f, f, f, f, f],
368  ["is_integer", f, t, t, t, f, t, t, f, f, f, f, f, f, f, f, f, f, f, f, f, f],
369  ["is_decimal", f, f, f, f, t, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f],
370  ["is_boolean", f, f, f, f, f, f, f, f, f, t, t, f, f, f, f, f, f, f, f, f, f],
371  ["is_string", f, f, f, f, f, f, f, f, f, f, f, t, t, t, f, f, f, f, f, f, f],
372  ["is_list", f, f, f, f, f, f, f, f, f, f, f, f, f, f, t, t, t, t, t, s, s],
373  ["is_range", f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, t, t],
374  ["is_even", s, f, t, t, f, t, t, s, s, s, s, s, s, s, s, s, s, s, s, s, s],
375  ["is_odd", s, t, f, f, f, f, f, s, s, s, s, s, s, s, s, s, s, s, s, s, s],
376  ["is_between_MM", f, t, t, t, t, t, t, f, f, t, t, f, f, f, f, f, f, f, f, f, f]
377  ];
378 
379  // sanity-test tables
380  table_check( test_r, test_c, false );
381  table_check( good_r, good_c, false );
382 
383  // validate helper function and module
384  function get_value( vid ) = get_table_v(test_r, test_c, vid, "tv");
385  module run_test( fname, fresult, vid )
386  {
387  value_text = get_table_v(test_r, test_c, vid, "td");
388  pass_value = get_table_v(good_r, good_c, fname, vid);
389 
390  test_pass = validate( cv=fresult, t=pass_value, pf=true );
391  test_text = validate( str(fname, "(", get_value(vid), ")=", pass_value), fresult, pass_value );
392 
393 
394  if ( pass_value != s )
395  {
396  if ( !test_pass )
397  log_warn( str(vid, "(", value_text, ") ", test_text) );
398  else if ( show_passing )
399  log_info( str(vid, " ", test_text) );
400  }
401  else if ( show_skipped )
402  log_info( str(vid, " *skip*: '", fname, "(", value_text, ")'") );
403  }
404 
405  // Indirect function calls would be very useful here!!!
406  for (vid=test_ids) run_test( "is_defined", is_defined(get_value(vid)), vid );
407  for (vid=test_ids) run_test( "not_defined", not_defined(get_value(vid)), vid );
408  for (vid=test_ids) run_test( "is_nan", is_nan(get_value(vid)), vid );
409  for (vid=test_ids) run_test( "is_inf", is_inf(get_value(vid)), vid );
410  for (vid=test_ids) run_test( "is_scalar", is_scalar(get_value(vid)), vid );
411  for (vid=test_ids) run_test( "is_iterable", is_iterable(get_value(vid)), vid );
412  for (vid=test_ids) run_test( "is_empty", is_empty(get_value(vid)), vid );
413  for (vid=test_ids) run_test( "is_number", is_number(get_value(vid)), vid );
414  for (vid=test_ids) run_test( "is_integer", is_integer(get_value(vid)), vid );
415  for (vid=test_ids) run_test( "is_decimal", is_decimal(get_value(vid)), vid );
416  for (vid=test_ids) run_test( "is_boolean", is_boolean(get_value(vid)), vid );
417  for (vid=test_ids) run_test( "is_string", is_string(get_value(vid)), vid );
418  for (vid=test_ids) run_test( "is_list", is_list(get_value(vid)), vid );
419  for (vid=test_ids) run_test( "is_range", is_range(get_value(vid)), vid );
420  for (vid=test_ids) run_test( "is_even", is_even(get_value(vid)), vid );
421  for (vid=test_ids) run_test( "is_odd", is_odd(get_value(vid)), vid );
422  for (vid=test_ids) run_test( "is_between_MM", is_between(get_value(vid),number_min,number_max), vid );
423 
424  // end-of-tests
425  END_OPENSCAD;
426 
427  BEGIN_MFSCRIPT;
428  include --path "${INCLUDE_PATH}" {config_base,config_csg}.mfs;
429  include --path "${INCLUDE_PATH}" script_std.mfs;
430  END_MFSCRIPT;
431 END_SCOPE;
432 */
433 
434 //----------------------------------------------------------------------------//
435 // end of file
436 //----------------------------------------------------------------------------//
function is_inf(v)
Test if a numerical value is infinite.
function is_empty(v)
Test if an iterable value is empty.
function is_integer(v)
Test if a value is an integer.
function is_scalar(v)
Test if a value is a single non-iterable value.
function is_boolean(v)
Test if a value is a predefined boolean constant.
function is_even(v)
Test if a numerical value is even.
function is_number(v)
Test if a value is a number.
function not_defined(v)
Test if a value is not defined.
function is_defined(v)
Test if a value is defined.
function is_range(v)
Test if a value is a range definition.
function is_list(v)
Test if a value is an iterable list of values.
function is_nan(v)
Test if a numerical value is invalid.
function is_decimal(v)
Test if a value is a decimal.
function is_between(v, l, u)
Test if a numerical value is between an upper and lower bounds.
function is_string(v)
Test if a value is a string.
number_max
The largest representable number in OpenSCAD scripts.
Definition: constants.scad:71
function is_iterable(v)
Test if a value has multiple parts and is iterable.
function is_odd(v)
Test if a numerical value is odd.