omdl  v0.5
OpenSCAD Mechanical Design Library
primitives.scad
Go to the documentation of this file.
1 //! Mathematical primitive functions.
2 /***************************************************************************//**
3  \file primitives.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  \details
29 
30  \note Include this library file using the \b include statement.
31 
32  \ingroup math prim_test prim_vector
33 *******************************************************************************/
34 
35 include <constants.scad>;
36 
37 //----------------------------------------------------------------------------//
38 /***************************************************************************//**
39  \page tv_prim Primitives Validation
40  \li \subpage tv_prim_test
41  \li \subpage tv_prim_vector
42 *******************************************************************************/
43 //----------------------------------------------------------------------------//
44 
45 //----------------------------------------------------------------------------//
46 /***************************************************************************//**
47  \page tv_prim_test Variable Tests
48  \li \subpage tv_prim_test_g1_s
49  \li \subpage tv_prim_test_g1_r
50  \li \subpage tv_prim_test_g2_s
51  \li \subpage tv_prim_test_g2_r
52 
53  \page tv_prim_test_g1_s Validation Script (group1)
54  \dontinclude primitives_validate_test_g1.scad
55  \skip include
56  \until end-of-tests
57  \page tv_prim_test_g1_r Validation Results (group1)
58  \include primitives_validate_test_g1.log
59 
60  \page tv_prim_test_g2_s Validation Script (group2)
61  \dontinclude primitives_validate_test_g2.scad
62  \skip include
63  \until end-of-tests
64  \page tv_prim_test_g2_r Validation Results (group2)
65  \include primitives_validate_test_g2.log
66 *******************************************************************************/
67 //----------------------------------------------------------------------------//
68 
69 //----------------------------------------------------------------------------//
70 /***************************************************************************//**
71  \addtogroup math
72  @{
73 
74  \defgroup prim_test Variable Tests
75  \brief Variable property test primitives.
76 
77  \details
78 
79  See validation results
80  \ref tv_prim_test_g1_r "group1" and \ref tv_prim_test_g2_r "group2".
81  @{
82 *******************************************************************************/
83 //----------------------------------------------------------------------------//
84 
85 //----------------------------------------------------------------------------//
86 // group 1
87 //----------------------------------------------------------------------------//
88 
89 //! Test if a value is defined.
90 /***************************************************************************//**
91  \param v <value> A value.
92 
93  \returns <boolean> \b true when the value is defined
94  and \b false otherwise.
95 *******************************************************************************/
96 function is_defined( v ) = (v == undef) ? false : true;
97 
98 //! Test if a value is not defined.
99 /***************************************************************************//**
100  \param v <value> A value.
101 
102  \returns <boolean> \b true when the value is not defined
103  and \b false otherwise.
104 *******************************************************************************/
105 function not_defined( v ) = (v == undef) ? true : false;
106 
107 //! Test if an iterable value is empty.
108 /***************************************************************************//**
109  \param v <value> An iterable value.
110 
111  \returns <boolean> \b true when the iterable value has zero elements
112  and \b false otherwise.
113 *******************************************************************************/
114 function is_empty( v ) = (len(v) == 0);
115 
116 //! Test if a value is a single non-iterable value.
117 /***************************************************************************//**
118  \param v <value> A value.
119 
120  \returns <boolean> \b true when the value is a single non-iterable value
121  and \b false otherwise.
122 
123  \details
124 
125  value is | defined result
126  :-------------:|:-----------------:
127  \b undef | \b true
128  \b inf | \b true
129  \b nan | \b true
130  integer | \b true
131  decimal | \b true
132  boolean | \b true
133  string | \b false
134  vector | \b false
135  range | not defined
136 *******************************************************************************/
137 function is_scalar( v ) = (len(v) == undef);
138 
139 //! Test if a value has multiple parts and is iterable.
140 /***************************************************************************//**
141  \param v <value> A value.
142 
143  \returns <boolean> \b true when the value is an iterable multi-part value
144  and \b false otherwise.
145 
146  \details
147 
148  value is | defined result
149  :-------------:|:-----------------:
150  \b undef | \b false
151  \b inf | \b false
152  \b nan | \b false
153  integer | \b false
154  decimal | \b false
155  boolean | \b false
156  string | \b true
157  vector | \b true
158  range | not defined
159 *******************************************************************************/
160 function is_iterable( v ) = (len(v) != undef);
161 
162 //! Test if a value is a string.
163 /***************************************************************************//**
164  \param v <value> A value.
165 
166  \returns <boolean> \b true when the value is a string
167  and \b false otherwise.
168 *******************************************************************************/
169 function is_string( v ) = (str(v) == v);
170 
171 //! Test if a value is a vector.
172 /***************************************************************************//**
173  \param v <value> A value.
174 
175  \returns <boolean> \b true when the value is a vector
176  and \b false otherwise.
177 *******************************************************************************/
178 function is_vector( v ) = is_iterable(v) && !is_string(v);
179 
180 //! Test if a value is a boolean constant.
181 /***************************************************************************//**
182  \param v <value> A value.
183 
184  \returns <boolean> \b true when the value is one of the predefined
185  boolean constants <tt>[true|false]</tt> and \b false otherwise.
186 *******************************************************************************/
187 function is_boolean
188 (
189  v
190 ) = is_string(v) ? false
191  : (str(v) == "true") ? true
192  : (str(v) == "false") ? true
193  : false;
194 
195 //! Test if a value is an integer.
196 /***************************************************************************//**
197  \param v <value> A value.
198 
199  \returns <boolean> \b true when the value is an integer
200  and \b false otherwise.
201 *******************************************************************************/
202 function is_integer
203 (
204  v
205 ) = not_defined(v) ? false
206  : ((v % 1) == 0);
207 
208 //! Test if a value is a decimal.
209 /***************************************************************************//**
210  \param v <value> A value.
211 
212  \returns <boolean> \b true when the value is a decimal
213  and \b false otherwise.
214 *******************************************************************************/
215 function is_decimal( v ) = ((v % 1) > 0);
216 
217 //! Test if a value is a number.
218 /***************************************************************************//**
219  \param v <value> A value.
220 
221  \returns <boolean> \b true when the value is a number
222  and \b false otherwise.
223 
224  \warning Returns \b true even for numerical values that are considered
225  infinite and invalid.
226 *******************************************************************************/
227 function is_number( v ) = is_defined(v % 1);
228 
229 //! Test if a value is a range definition.
230 /***************************************************************************//**
231  \param v <value> A value.
232 
233  \returns <boolean> \b true when the value is a range definition
234  and \b false otherwise.
235 
236  \details
237 
238  \internal
239  Currently a range is determined to be that which does not fit in any
240  other value category. This is likely to fail as OpenSCAD matures.
241  This exclusion test should be replaced by a suitable inclusion test
242  when possible.
243  \endinternal
244 *******************************************************************************/
245 function is_range
246 (
247  v
248 ) = is_defined(v) &&
249  !is_iterable(v) &&
250  !is_boolean(v) &&
251  !is_integer(v) &&
252  !is_decimal(v) &&
253  !is_nan(v) &&
254  !is_inf(v);
255 
256 //! Test if a numerical value is invalid.
257 /***************************************************************************//**
258  \param v <value> A numerical value.
259 
260  \returns <boolean> \b true when the value is determined to be \b nan
261  (Not A Number) and \b false otherwise.
262 *******************************************************************************/
263 function is_nan( v ) = ( v != v );
264 
265 //! Test if a numerical value is infinite.
266 /***************************************************************************//**
267  \param v <value> A numerical value.
268 
269  \returns <boolean> \b true when the value is determined to be
270  \b inf (greater than the largest representable number)
271  and \b false otherwise.
272 *******************************************************************************/
273 function is_inf( v ) = ( v == (number_max * number_max) );
274 
275 //! Test if a numerical value is even.
276 /***************************************************************************//**
277  \param v <value> A numerical value.
278 
279  \returns <boolean> \b true when the value is determined to be \e even
280  and \b false otherwise.
281 
282  \details
283 
284  \note The value must be valid and defined but may be positive or
285  negative. Any value that is not an integer returns \b false.
286 *******************************************************************************/
287 function is_even( v ) = !is_integer(v) ? false : ((v % 2) == 0);
288 
289 //! Test if a numerical value is odd.
290 /***************************************************************************//**
291  \param v <value> A numerical value.
292 
293  \returns <boolean> \b true when the value is determined to be \e odd
294  and \b false otherwise.
295 
296  \details
297 
298  \note The value must be valid and defined but may be positive or
299  negative. Any value that is not an integer returns \b false.
300 *******************************************************************************/
301 function is_odd( v ) = !is_integer(v) ? false : ((v % 2) != 0);
302 
303 //----------------------------------------------------------------------------//
304 // group 2
305 //----------------------------------------------------------------------------//
306 
307 //! Test if all elements of a value equal a comparison value.
308 /***************************************************************************//**
309  \param v <value> A value or an iterable value.
310  \param cv <value> A comparison value.
311 
312  \returns <boolean> \b true when all elements equal the value \p cv
313  and \b false otherwise.
314 
315  \details
316 
317  \warning Always returns \b true when \p v is empty.
318 *******************************************************************************/
319 function all_equal
320 (
321  v,
322  cv
323 ) = !is_iterable(v) ? (v == cv)
324  : is_empty(v) ? true
325  : (first(v) != cv) ? false
326  : all_equal(ntail(v), cv);
327 
328 //! Test if any element of a value equals a comparison value.
329 /***************************************************************************//**
330  \param v <value> A value or an iterable value.
331  \param cv <value> A comparison value.
332 
333  \returns <boolean> \b true when any element equals the value \p cv
334  and \b false otherwise.
335 
336  \details
337 
338  \warning Always returns \b false when \p v is empty.
339 *******************************************************************************/
340 function any_equal
341 (
342  v,
343  cv
344 ) = !is_iterable(v) ? (v == cv)
345  : is_empty(v) ? false
346  : (first(v) == cv) ? true
347  : any_equal(ntail(v), cv);
348 
349 //! Test if no element of a value is undefined.
350 /***************************************************************************//**
351  \param v <value> A value or an iterable value.
352 
353  \returns <boolean> \b true when no element is undefined
354  and \b false otherwise.
355 
356  \details
357 
358  \warning Always returns \b true when \p v is empty.
359 *******************************************************************************/
360 function all_defined(v) = !any_equal(v, undef);
361 
362 //! Test if any element of a value is undefined.
363 /***************************************************************************//**
364  \param v <value> A value or an iterable value.
365 
366  \returns <boolean> \b true when any element is undefined
367  and \b false otherwise.
368 
369  \details
370 
371  \warning Always returns \b false when \p v is empty.
372 *******************************************************************************/
373 function any_undefined(v) = any_equal(v, undef);
374 
375 //! Test if all elements of a value are scalars.
376 /***************************************************************************//**
377  \param v <value> A value or an iterable value.
378 
379  \returns <boolean> \b true when all elements are scalar values
380  and \b false otherwise.
381  Returns \b true when \p v is a single scalar value.
382  Returns the value of \p v when it is not defined.
383 
384  \details
385 
386  \warning Always returns \b true when \p v is empty.
387 *******************************************************************************/
388 function all_scalars
389 (
390  v
391 ) = not_defined(v) ? v
392  : is_scalar(v) ? true
393  : is_empty(v) ? true
394  : !is_scalar(first(v)) ? false
395  : all_scalars(ntail(v));
396 
397 //! Test if all elements of a value are vectors.
398 /***************************************************************************//**
399  \param v <value> A value or an iterable value.
400 
401  \returns <boolean> \b true when all elements are vector values
402  and \b false otherwise.
403  Returns \b true when \p v is a single vector value.
404  Returns the value of \p v when it is not defined.
405 
406  \details
407 
408  \warning Always returns \b true when \p v is empty.
409 *******************************************************************************/
410 function all_vectors
411 (
412  v
413 ) = not_defined(v) ? v
414  : is_scalar(v) ? false
415  : is_empty(v) ? true
416  : !is_vector(first(v)) ? false
417  : all_vectors(ntail(v));
418 
419 //! Test if all elements of a value are strings.
420 /***************************************************************************//**
421  \param v <value> A value or an iterable value.
422 
423  \returns <boolean> \b true when all elements are string values
424  and \b false otherwise.
425  Returns \b true when \p v is a single string value.
426  Returns the value of \p v when it is not defined.
427 
428  \details
429 
430  \warning Always returns \b true when \p v is empty.
431 *******************************************************************************/
432 function all_strings
433 (
434  v
435 ) = not_defined(v) ? v
436  : is_scalar(v) ? false
437  : is_empty(v) ? true
438  : !is_string(first(v)) ? false
439  : all_strings(ntail(v));
440 
441 //! Test if all elements of a value are numbers.
442 /***************************************************************************//**
443  \param v <value> A value or an iterable value.
444 
445  \returns <boolean> \b true when all elements are numerical values
446  and \b false otherwise.
447  Returns \b true when \p v is a single numerical value.
448  Returns the value of \p v when it is not defined.
449 
450  \details
451 
452  \warning Always returns \b true when \p v is empty.
453 *******************************************************************************/
454 function all_numbers
455 (
456  v
457 ) = not_defined(v) ? v
458  : is_scalar(v) ? is_number(v)
459  : is_empty(v) ? true
460  : !is_number(first(v)) ? false
461  : all_numbers(ntail(v));
462 
463 //! Test if all elements of a value have a given length.
464 /***************************************************************************//**
465  \param v <value> A value or an iterable value.
466  \param l <integer> The length.
467 
468  \returns <boolean> \b true when all elements have length equal to \p l
469  and \b false otherwise.
470  Returns the value of \p v when it is not defined.
471 
472  \details
473 
474  \warning Always returns \b true when \p v is empty.
475 *******************************************************************************/
476 function all_len
477 (
478  v,
479  l
480 ) = not_defined(v) ? v
481  : is_scalar(v) ? false
482  : is_empty(v) ? true
483  : (len(first(v)) != l) ? false
484  : all_len(ntail(v),l);
485 
486 //! Test if all elements of two values are approximately equal.
487 /***************************************************************************//**
488  \param v1 <value> A value or an iterable value 1.
489  \param v2 <value> A value or an iterable value 2.
490  \param p <number> A numerical precision.
491 
492  \returns <boolean> \b true when all elements of each values are
493  sufficiently equal and \b false otherwise. All numerical
494  comparisons are performed with precision limited by \p p. All
495  non-numeric comparisons test for exact equality.
496 
497  \details
498 
499  \note The parameter \p p indicated the number of digits of precision
500  for each numerical comparison.
501 
502  \warning Always returns \b true when \p v is empty.
503 *******************************************************************************/
504 function almost_equal
505 (
506  v1,
507  v2,
508  p = 4
509 ) = all_scalars([v1, v2]) ?
510  (
511  all_numbers([v1, v2]) ? ( (abs(v1-v2) * pow(10, p)) < 1 )
512  : (v1 == v2)
513  )
514  : (is_string(v1) || is_string(v2)) ? (v1 == v2)
515  : all_equal([v1, v2], empty_v) ? true
516  : any_equal([v1, v2], empty_v) ? false
517  : !almost_equal(first(v1), first(v2), p) ? false
518  : almost_equal(ntail(v1), ntail(v2), p);
519 
520 //! Compare any two values (may be iterable and/or of different types).
521 /***************************************************************************//**
522  \param v1 <value> A value or an iterable value 1.
523  \param v2 <value> A value or an iterable value 2.
524  \param s <boolean> Order ranges by their numerical sum.
525 
526  \returns <integer> \b -1 when <tt>(v2 < v1)</tt>,
527  \b +1 when <tt>(v2 > v1)</tt>, and
528  \b 0 when <tt>(v2 == v1)</tt>.
529 
530  \details
531 
532  The following table summarizes how values are ordered.
533 
534  order | type | \p s | intra-type ordering
535  :-----:|:--------:|:---------:|:--------------------------------------
536  1 | \b undef | | (singular)
537  2 | number | | numerical comparison
538  3 | string | | lexical comparison
539  4 | boolean | | \b false < \b true
540  5 | vector | | lengths then element-wise comparison
541  6 | range | \b true | compare sum of range elements
542  6 | range | \b false | lengths then element-wise comparison
543 
544  \note When comparing two vectors of equal length, the comparison
545  continue element-by-element until an ordering can be
546  determined. Two vectors are declared equal when all elements
547  have been compared and no ordering has been determined.
548 
549  \warning The performance of element-wise comparisons of vectors
550  degrades exponentially with vector size.
551  \warning The sum of a range may quickly exceeded the intermediate
552  variable storage capacity for long ranges.
553 *******************************************************************************/
554 function compare
555 (
556  v1,
557  v2,
558  s = true
559 ) = let( v2_nd = not_defined(v2) )
560  not_defined(v1) ?
561  (
562  v2_nd ? 0
563  : 1 // others are greater
564  )
565  // v1 a number
566  : let( v2_in = is_number(v2) )
567  is_number(v1) ?
568  (
569  v2_nd ? -1
570  : v2_in ?
571  (
572  (v1 > v2) ? -1
573  : (v2 > v1) ? +1
574  : 0
575  )
576  : 1 // others are greater
577  )
578  // v1 a string
579  : let( v2_is = is_string(v2) )
580  is_string(v1) ?
581  (
582  (v2_nd || v2_in) ? -1
583  : v2_is ?
584  (
585  (v1 > v2) ? -1
586  : (v2 > v1) ? +1
587  : 0
588  )
589  : 1 // others are greater
590  )
591  // v1 a boolean
592  : let( v2_ib = is_boolean(v2) )
593  is_boolean(v1) ?
594  (
595  (v2_nd || v2_in || v2_is) ? -1
596  : v2_ib ?
597  (
598  ((v1 == true) && (v2 == false)) ? -1 // defined: true > false
599  : ((v1 == false) && (v2 == true)) ? +1
600  : 0
601  )
602  : 1 // others are greater
603  )
604  // v1 a vector
605  : let( v2_iv = is_vector(v2) )
606  is_vector(v1) ?
607  (
608  (v2_nd || v2_in || v2_is || v2_ib) ? -1
609  : v2_iv ?
610  (
611  let
612  (
613  l1 = len(smerge(v1, true)), // get total element count
614  l2 = len(smerge(v2, true))
615  )
616  (l1 > l2) ? -1 // longest vector is greater
617  : (l2 > l1) ? +1
618  : ((l1 == 0) && (l2 == 0)) ? 0 // reached end, are equal
619  : let
620  (
621  cf = compare(first(v1), first(v2), s) // compare first elements
622  )
623  (cf != 0) ? cf // not equal, ordering determined
624  : compare(ntail(v1), ntail(v2), s) // equal, check remaining
625  )
626  : 1 // others are greater
627  )
628  // v1 assume a range.
629  : is_range(v2) ?
630  (
631  (v1 == v2) ? 0 // equal range definitions
632  // compare range sums
633  : (s == true) ?
634  (
635  let
636  (
637  rs1 = sum(v1), // compute range sums
638  rs2 = sum(v2)
639  )
640  (rs1 > rs2) ? -1 // greatest sum is greater
641  : (rs2 > rs1) ? +1
642  : 0 // sums equal
643  )
644  // compare range vectors
645  : (
646  let
647  (
648  rv1 = [for (i=v1) i], // convert to vectors
649  rv2 = [for (i=v2) i],
650  rl1 = len(rv1), // get lengths
651  rl2 = len(rv2)
652  )
653  (rl1 > rl2) ? -1 // longest range is greater
654  : (rl2 > rl1) ? +1
655  : compare(rv1, rv2, s) // equal so compare as vectors
656  )
657  )
658  // v2 not a range so v1 > v2
659  : -1;
660 
661 //! @}
662 //! @}
663 
664 //----------------------------------------------------------------------------//
665 /***************************************************************************//**
666  \page tv_prim_vector Vector Operations
667  \li \subpage tv_prim_vector_s
668  \li \subpage tv_prim_vector_r
669  \page tv_prim_vector_s Validation Script
670  \dontinclude primitives_validate_vector.scad
671  \skip include
672  \until end-of-tests
673  \page tv_prim_vector_r Validation Results
674  \include primitives_validate_vector.log
675 *******************************************************************************/
676 //----------------------------------------------------------------------------//
677 
678 //----------------------------------------------------------------------------//
679 /***************************************************************************//**
680  \addtogroup math
681  @{
682 
683  \defgroup prim_vector Vector Operations
684  \brief Vector operation primitives.
685 
686  \details
687 
688  See validation \ref tv_prim_vector_r "results".
689  @{
690 *******************************************************************************/
691 //----------------------------------------------------------------------------//
692 
693 //----------------------------------------------------------------------------//
694 // create / convert
695 //----------------------------------------------------------------------------//
696 
697 //! Create a vector of constant elements.
698 /***************************************************************************//**
699  \param l <integer> The vector length.
700  \param v <value> The element value.
701 
702  \returns <vector> With \p l copies of the element value \p v.
703  Returns \b empty_v when \p l is not a number or if
704  <tt>(l < 1)</tt>.
705 
706  \details
707 
708  \note When \p v is not specified, each element is assigned the value
709  of its index position.
710 *******************************************************************************/
711 function consts
712 (
713  l,
714  v
715 ) = (l<1) ? empty_v
716  : !is_number(l) ? empty_v
717  : is_defined(v) ? [for (i=[0:1:l-1]) v]
718  : [for (i=[0:1:l-1]) i];
719 
720 //! Convert all vector elements to strings and concatenate.
721 /***************************************************************************//**
722  \param v <vector> A vector of values.
723 
724  \returns <string> Constructed by converting each element of the vector
725  to a string and concatenating together.
726  Returns \b undef when \p v is not defined.
727 
728  \details
729 
730  \b Example
731  \code{.C}
732  v1=["a", "b", "c", "d"];
733  v2=[1, 2, 3];
734 
735  echo( vstr(concat(v1, v2)) );
736  \endcode
737 
738  \b Result
739  \code{.C}
740  ECHO: "abcd123"
741  \endcode
742 *******************************************************************************/
743 function vstr
744 (
745  v
746 ) = not_defined(v) ? undef
747  : !is_iterable(v) ? str(v)
748  : is_empty(v) ? empty_str
749  : (len(v) == 1) ? str(first(v))
750  : str(first(v), vstr(ntail(v)));
751 
752 //! Compute the sum of a vector of numbers.
753 /***************************************************************************//**
754  \param v <range|vector> A vector of numerical values.
755  \param i1 <integer> The element index at which to begin summation
756  (first when not specified).
757  \param i2 <integer> The element index at which to end summation
758  (last when not specified).
759 
760  \returns <decimal> The summation of elements over the index range.
761  Returns \b v when it is a scalar number.
762  Returns 0 when \p v is empty.
763  Returns \b undef when \p v is not defined or is not iterable
764  and not a number.
765 *******************************************************************************/
766 function sum
767 (
768  v,
769  i1,
770  i2
771 ) = not_defined(v) ? undef
772  : is_empty(v) ? 0
773  : is_number(v) ? v
774  : is_range(v) ? sum([for (i=v) i], i1, i2)
775  : !is_iterable(v) ? undef
776  : let
777  (
778  s = is_defined(i1) ? min(max(i1,0),len(v)-1) : 0,
779  i = is_defined(i2) ? max(min(i2,len(v)-1),0) : len(v)-1
780  )
781  (i == s) ? v[i]
782  : v[i] + sum(v, s, i-1);
783 
784 //----------------------------------------------------------------------------//
785 // query
786 //----------------------------------------------------------------------------//
787 
788 //! Find the occurrences of a match value in an iterable value.
789 /***************************************************************************//**
790  \param mv <value> A match value.
791  \param v <value> An iterable value.
792  \param c <integer> A match count.
793  For <tt>(c>=1)</tt>, return the first \p c matches.
794  For <tt>(c<=0)</tt>, return all matches.
795  \param i <integer> The element column index to match.
796  \param i1 <integer> The element index where find begins (default: first).
797  \param i2 <integer> The element index where find ends (default: last).
798 
799  \returns <vector> Of indexes where elements match \p mv.
800  Returns \b empty_v when no element of \p v matches \p mv
801  or when \p v is not iterable.
802 
803  \details
804 
805  The use-cases for find() and [search()] are summarized in the
806  following tables.
807 
808  \b Find:
809 
810  | mv / v | string | vector of scalars | vector of iterables |
811  |---------------------|:------:|:-----------------:|:-------------------:|
812  | scalar | | (a) | (b) see note 1 |
813  | string | (c) | | (b) see note 1 |
814  | vector of scalars | | | (b) see note 1 |
815  | vector of iterables | | | (b) see note 1 |
816 
817  \b Search:
818 
819  | mv / v | string | vector of scalars | vector of iterables |
820  |---------------------|:------:|:-----------------:|:-------------------:|
821  | scalar | | (a) | (b) |
822  | string | (d) | invalid | (e) see note 2 |
823  | vector of scalars | | (f) | (g) |
824  | vector of iterables | | | (g) |
825 
826  \b Key:
827 
828  \li (a) Identify each element of \p v that equals \p mv.
829  \li (b) Identify each element of \p v where \p mv equals the element at
830  the specified column index, \p i, of each iterable value in \p v.
831  \li (c) If, and only if, \p mv is a single character, identify each
832  character in \p v that equals \p mv.
833  \li (d) For each character of \p mv, identify where it exists in \p v.
834  \b empty_v is returned for each character of \p mv absent from \p v.
835  \li (e) For each character of \p mv, identify where it exists in \p v
836  either as a numeric value or as a character at the specified column
837  index, \p i.
838  \b empty_v is returned for each character of \p mv absent from \p v.
839  \li (f) For each scalar of \p mv, identify where it exists in \p v.
840  \b empty_v is returned for each scalar of \p mv absent from \p v.
841  \li (g) For each element of \p mv, identify where it equals the element
842  at the specified column index, \p i, of each iterable value in \p v.
843  \b empty_v is returned for each element of \p mv absent from \p v
844  in the specified column index.
845 
846  \note \b 1: When \p i is specified, that element column is compared.
847  Otherwise, the entire element is compared. Functions find()
848  and [search()] behave differently in this regard.
849 
850  \note \b 2: Invalid use combination when any element of \p v is a
851  string. However, an element that is a vector of one or more
852  strings is valid. In which case, only the first character of
853  each string element is considered.
854 
855  [search()]: https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Other_Language_Features#Search
856 *******************************************************************************/
857 function find
858 (
859  mv,
860  v,
861  c = 1,
862  i,
863  i1 = 0,
864  i2
865 ) = !is_iterable(v) ? empty_v
866  : (i1 > i2) ? empty_v
867  : (i1 > len(v)-1) ? empty_v
868  : ((not_defined(i) && (v[i1] == mv)) || (v[i1][i] == mv)) ?
869  (
870  (c == 1) ? [i1]
871  : concat(i1, find(mv, v, c-1, i, i1+1, i2))
872  )
873  : find(mv, v, c, i, i1+1, i2);
874 
875 //! Count all occurrences of a match value in an iterable value.
876 /***************************************************************************//**
877  \param mv <value> A match value.
878  \param v <value> An iterable value.
879  \param s <boolean> Use search for element matching (\b false uses find).
880  \param i <integer> The element column index to match.
881 
882  \returns <integer> The number of times \p mv occurs in \p v.
883 
884  \details
885 
886  See find() for information on value matching.
887 *******************************************************************************/
888 function count
889 (
890  mv,
891  v,
892  s = true,
893  i
894 ) = (s == false) ?
895  len(find(mv, v, 0, i))
896  : len(smerge(search(mv, v, 0, i)));
897 
898 //! Check the existence of a match value in an iterable value.
899 /***************************************************************************//**
900  \param mv <value> A match value.
901  \param v <value> An iterable value.
902  \param s <boolean> Use search for element matching (\b false uses find).
903  \param i <integer> The element column index to match.
904 
905  \returns <boolean> \b true when \p mv exists in \p v and \b false otherwise.
906 
907  \details
908 
909  See find() for information on value matching.
910 *******************************************************************************/
911 function exists
912 (
913  mv,
914  v,
915  s = true,
916  i
917 ) = (s == false) ?
918  (find(mv, v, 1, i) != empty_v)
919  : (strip(search(mv, v, 1, i)) != empty_v);
920 
921 //----------------------------------------------------------------------------//
922 // select
923 //----------------------------------------------------------------------------//
924 
925 //! Return a defined or default value.
926 /***************************************************************************//**
927  \param v <value> A value.
928  \param d <value> A default value.
929 
930  \returns <value> \p v when it is defined or \p d otherwise.
931 *******************************************************************************/
932 function defined_or
933 (
934  v,
935  d
936 ) = is_defined(v) ? v : d;
937 
938 //! Return a defined vector element or default value.
939 /***************************************************************************//**
940  \param v <vector> A vector.
941  \param i <integer> An element index.
942  \param d <value> A default value.
943 
944  \returns <value> <tt>v[i]</tt> when it is defined or \p d otherwise.
945 *******************************************************************************/
946 function edefined_or
947 (
948  v,
949  i,
950  d
951 ) = (len(v) > i) ? v[i] : d;
952 
953 //! Return the first element of an iterable value.
954 /***************************************************************************//**
955  \param v <value> An iterable value.
956 
957  \returns <value> The first element of \p v.
958  Returns \b undef when \p v is not defined, is not iterable,
959  or is empty.
960 *******************************************************************************/
961 function first
962 (
963  v
964 ) = !is_iterable(v) ? undef
965  : v[0];
966 
967 //! Return the second element of an iterable value.
968 /***************************************************************************//**
969  \param v <value> An iterable value.
970 
971  \returns <value> The second element of \p v.
972  Returns \b undef when \p v is not defined, is not iterable,
973  or is empty.
974 *******************************************************************************/
975 function second
976 (
977  v
978 ) = !is_iterable(v) ? undef
979  : v[1];
980 
981 //! Return the last element of an iterable value.
982 /***************************************************************************//**
983  \param v <value> An iterable value.
984 
985  \returns <value> The last element of \p v.
986  Returns \b undef when \p v is not defined, is not iterable,
987  or is empty.
988 *******************************************************************************/
989 function last
990 (
991  v
992 ) = not_defined(v) ? undef
993  : !is_iterable(v) ? undef
994  : is_empty(v) ? undef
995  : v[len(v)-1];
996 
997 //! Return a vector containing the first n elements of an iterable value.
998 /***************************************************************************//**
999  \param v <value> An iterable value.
1000  \param n <integer> An element count.
1001 
1002  \returns <vector> Containing the first \p n elements of \p v.
1003  Returns \b undef when \p v is not defined, is not iterable,
1004  or is empty.
1005 *******************************************************************************/
1006 function nfirst
1007 (
1008  v,
1009  n = 1
1010 ) = not_defined(v) ? undef
1011  : !is_iterable(v) ? undef
1012  : is_empty(v) ? undef
1013  : n < 1 ? empty_v
1014  : [for (i = [0 : min(n-1, len(v)-1)]) v[i]];
1015 
1016 //! Return a vector containing the last n elements of an iterable value.
1017 /***************************************************************************//**
1018  \param v <value> An iterable value.
1019  \param n <integer> An element count.
1020 
1021  \returns <vector> Containing the last \p n elements of \p v.
1022  Returns \b undef when \p v is not defined, is not iterable,
1023  or is empty.
1024 *******************************************************************************/
1025 function nlast
1026 (
1027  v,
1028  n = 1
1029 ) = not_defined(v) ? undef
1030  : !is_iterable(v) ? undef
1031  : is_empty(v) ? undef
1032  : n < 1 ? empty_v
1033  : [for (i = [max(0, len(v)-n) : len(v)-1]) v[i]];
1034 
1035 //! Return a vector containing all but the last n elements of an iterable value.
1036 /***************************************************************************//**
1037  \param v <value> An iterable value.
1038  \param n <integer> An element count.
1039 
1040  \returns <vector> Containing all but the last \p n elements of \p v.
1041  Returns \b empty_v when \p v contains fewer than \p n elements.
1042  Returns \b undef when \p v is not defined, is not iterable,
1043  or is empty.
1044 *******************************************************************************/
1045 function nhead
1046 (
1047  v,
1048  n = 1
1049 ) = not_defined(v) ? undef
1050  : !is_iterable(v) ? undef
1051  : is_empty(v) ? undef
1052  : (n >= len(v)) ? empty_v
1053  : [for (i = [0 : min(len(v)-1, len(v)-1-n)]) v[i]];
1054 
1055 //! Return a vector containing all but the first n elements of an iterable value.
1056 /***************************************************************************//**
1057  \param v <value> An iterable value.
1058  \param n <integer> An element count.
1059 
1060  \returns <vector> Containing all but the first n elements of \p v.
1061  Returns \b empty_v when \p v contains fewer than \p n elements.
1062  Returns \b undef when \p v is not defined, is not iterable,
1063  or is empty.
1064 *******************************************************************************/
1065 function ntail
1066 (
1067  v,
1068  n = 1
1069 ) = not_defined(v) ? undef
1070  : !is_iterable(v) ? undef
1071  : is_empty(v) ? undef
1072  : (n >= len(v)) ? empty_v
1073  : [for (i = [max(0, n) : len(v)-1]) v[i]];
1074 
1075 //! Select a range of elements from an iterable value.
1076 /***************************************************************************//**
1077  \param v <value> An iterable value.
1078  \param i <range|vector|integer> Index selection.
1079 
1080  \returns <vector> Containing the vector element indexes selected in \p i.
1081  Returns \b undef when \p i does not map to an element of \p v.
1082  Returns \b empty_v when \p v is empty.
1083  Returns \b undef when \p v is not defined or is not iterable.
1084 *******************************************************************************/
1085 function rselect
1086 (
1087  v,
1088  i
1089 ) = !all_defined([v, i]) ? undef
1090  : !is_iterable(v) ? undef
1091  : is_empty(v) ? empty_v
1092  : is_number(i) && ((i<0) || (i>(len(v)-1))) ? undef
1093  : is_vector(i) && ((min([for (y=i) y])<0) || (max([for (y=i) y])>(len(v)-1))) ? undef
1094  : is_range(i) && ((min([for (y=i) y])<0) || (max([for (y=i) y])>(len(v)-1))) ? undef
1095  : let
1096  (
1097  s = is_number(i) ? [i] : i
1098  )
1099  [for (j = [for (k=s) k]) v[j]];
1100 
1101 //! Select an element from each iterable value.
1102 /***************************************************************************//**
1103  \param v <vector> A vector of iterable values.
1104  \param f <boolean> Select the first element.
1105  \param l <boolean> Select the last element.
1106  \param i <integer> Select a numeric element index position.
1107 
1108  \returns <vector> Containing the selected element of each iterable value
1109  of \p v.
1110  Returns \b empty_v when \p v is empty.
1111  Returns \b undef when \p v is not defined or is not iterable.
1112 
1113  \details
1114 
1115  \note When more than one selection criteria is specified, the
1116  order of precedence is: \p i, \p l, \p f.
1117 *******************************************************************************/
1118 function eselect
1119 (
1120  v,
1121  f = true,
1122  l = false,
1123  i
1124 ) = not_defined(v) ? undef
1125  : !is_iterable(v) ? undef
1126  : is_empty(v) ? empty_v
1127  : is_defined(i) ? concat( [first(v)[i]], eselect(ntail(v), f, l, i) )
1128  : (l == true) ? concat( [last(first(v))], eselect(ntail(v), f, l, i) )
1129  : (f == true) ? concat( [first(first(v))], eselect(ntail(v), f, l, i) )
1130  : undef;
1131 
1132 //! Case-like select a value from a vector of ordered options by index.
1133 /***************************************************************************//**
1134  \param v <vector> A vector of values.
1135  \param i <integer> Element selection index.
1136 
1137  \returns <value> The value of the vector element at the specified index.
1138  Returns the default value when \p i does not map to an element
1139  of \p v or when \p i is undefined.
1140 
1141  \details
1142 
1143  Behaves like a case statement for selecting values from a list of
1144  <em>ordered options</em>.
1145  The default value is: <tt>last(v)<tt>.
1146 
1147  \b Example
1148  \code{.C}
1149  ov = [ "value1", "value2", "default" ];
1150 
1151  ciselect( ov ); // "default"
1152  ciselect( ov, 4 ); // "default"
1153  ciselect( ov, 0 ); // "value1"
1154  \endcode
1155 *******************************************************************************/
1156 function ciselect
1157 (
1158  v,
1159  i
1160 ) = not_defined(i) ? last(v)
1161  : !is_integer(i) ? last(v)
1162  : (i < 0) ? last(v)
1163  : (i > len(v)-1) ? last(v)
1164  : v[i];
1165 
1166 //! Case-like select a value from a vector of identified options by match-value.
1167 /***************************************************************************//**
1168  \param v <vector> A two dimensional vector of one or more identified
1169  values [[identifier, value], ...].
1170  \param mv <value> Element selection match value.
1171 
1172  \returns <value> The value from the vector of identified elements
1173  with an identifier matching \p mv.
1174  Returns the default value when \p mv does not match any of
1175  the element identifiers of \p v or when \p mv is undefined.
1176 
1177  \details
1178 
1179  Behaves like a case statement for selecting values from a list of
1180  <em>identified options</em>.
1181  The default value is: <tt>second(last(v))<tt>.
1182 
1183  \b Example
1184  \code{.C}
1185  ov = [ [0,"value0"], ["a","value1"], ["b","value2"], ["c","default"] ];
1186 
1187  cmvselect( ov ); // "default"
1188  cmvselect( ov, "x" ); // "default"
1189  cmvselect( ov, 0 ); // "value0"
1190  cmvselect( ov, "b" ); // "value2"
1191  \endcode
1192 *******************************************************************************/
1193 function cmvselect
1194 (
1195  v,
1196  mv
1197 ) = not_defined(mv) ? second(last(v))
1198  : let
1199  (
1200  i = first(search([mv], v, 1, 0))
1201  )
1202  is_empty(i) ? second(last(v))
1203  : second(v[i]);
1204 
1205 //----------------------------------------------------------------------------//
1206 // reorder
1207 //----------------------------------------------------------------------------//
1208 
1209 //! Serial-merge vectors of iterable values.
1210 /***************************************************************************//**
1211  \param v <vector> A vector of iterable values.
1212  \param r <boolean> Recursively merge iterable elements.
1213 
1214  \returns <vector> Containing the serial-wise element concatenation
1215  of each element in \p v.
1216  Returns \b empty_v when \p v is empty.
1217  Returns \b undef when \p v is not defined.
1218 
1219  \details
1220 
1221  \note A string, although iterable, is treated as a merged unit.
1222 *******************************************************************************/
1223 function smerge
1224 (
1225  v,
1226  r = false
1227 ) = not_defined(v) ? undef
1228  : !is_iterable(v) ? [v]
1229  : is_empty(v) ? empty_v
1230  : is_string(v) ? [v]
1231  : ((r == true) && is_iterable(first(v))) ?
1232  concat(smerge(first(v), r), smerge(ntail(v), r))
1233  : concat(first(v), smerge(ntail(v), r));
1234 
1235 //! Parallel-merge vectors of iterable values.
1236 /***************************************************************************//**
1237  \param v <vector> A vector of iterable values.
1238  \param j <boolean> Join each merge as a vector.
1239 
1240  \returns <vector> Containing the parallel-wise element concatenation
1241  of each iterable value in \p v.
1242  Returns \b empty_v when any element value in \p v is empty.
1243  Returns \b undef when \p v is not defined or when any element
1244  value in \p v is not iterable.
1245 
1246  \details
1247 
1248  \b Example
1249  \code{.C}
1250  v1=["a", "b", "c", "d"];
1251  v2=[1, 2, 3];
1252 
1253  echo( pmerge( [v1, v2], true ) );
1254  echo( pmerge( [v1, v2], false ) );
1255  \endcode
1256 
1257  \b Result
1258  \code{.C}
1259  ECHO: [["a", 1], ["b", 2], ["c", 3]]
1260  ECHO: ["a", 1, "b", 2, "c", 3]
1261  \endcode
1262 
1263  \note The resulting vector length will be limited by the iterable
1264  value with the shortest length.
1265  \note A string, although iterable, is treated as a merged unit.
1266 *******************************************************************************/
1267 function pmerge
1268 (
1269  v,
1270  j = true
1271 ) = not_defined(v) ? undef
1272  : !is_iterable(v) ? undef
1273  : is_empty(v) ? empty_v
1274  : is_string(v) ? [v]
1275  : let
1276  (
1277  l = [for (i = v) len(i)] // element lengths
1278  )
1279  any_undefined(l) ? undef // any element not iterable?
1280  : (min(l) == 0) ? empty_v // any element empty?
1281  : let
1282  (
1283  h = [for (i = v) first(i)],
1284  t = [for (i = v) ntail(i)]
1285  )
1286  (j == true) ? concat([h], pmerge(t, j))
1287  : concat(h, pmerge(t, j));
1288 
1289 //! Reverse the elements of an iterable value.
1290 /***************************************************************************//**
1291  \param v <value> An iterable value.
1292 
1293  \returns <vector> Containing the elements of \p v in reversed order.
1294  Returns \b empty_v when \p v is empty.
1295  Returns \b undef when \p v is not defined or is not iterable.
1296 *******************************************************************************/
1297 function reverse
1298 (
1299  v
1300 ) = not_defined(v) ? undef
1301  : !is_iterable(v) ? undef
1302  : is_empty(v) ? empty_v
1303  : [for (i = [len(v)-1 : -1 : 0]) v[i]];
1304 
1305 //! Sort the numeric or string elements of a vector using quick sort.
1306 /***************************************************************************//**
1307  \param v <vector> A vector of values.
1308  \param r <boolean> Reverse sort order.
1309 
1310  \returns <vector> With elements sorted in ascending order.
1311  Returns \b undef when \p v is not all strings or all numbers.
1312  Returns \b undef when \p v is not defined or is not a vector.
1313 
1314  \details
1315 
1316  \warning This implementation relies on the comparison operators
1317  '<' and '>' which expect the operands to be either two scalar
1318  numbers or two strings. Therefore, this function returns \b undef
1319  for vectors containing anything other than all scalar numbers
1320  or all strings.
1321 
1322  See [Wikipedia](https://en.wikipedia.org/wiki/Quicksort)
1323  for more information.
1324 *******************************************************************************/
1325 function qsort
1326 (
1327  v,
1328  r = false
1329 ) = not_defined(v) ? undef
1330  : !is_vector(v) ? undef
1331  : is_empty(v) ? empty_v
1332  : !(all_strings(v) || all_numbers(v)) ? undef // not all numbers or strings
1333  : let
1334  (
1335  mp = v[floor(len(v)/2)],
1336 
1337  lt = [for (i = v) if (i < mp) i],
1338  eq = [for (i = v) if (i == mp) i],
1339  gt = [for (i = v) if (i > mp) i]
1340 
1341  )
1342  (r == true) ? concat(qsort(gt, r), eq, qsort(lt, r))
1343  : concat(qsort(lt, r), eq, qsort(gt, r));
1344 
1345 //! Hierarchically sort all elements of a vector using quick sort.
1346 /***************************************************************************//**
1347  \param v <vector> A vector of values.
1348  \param d <integer> Recursive sort depth.
1349  \param r <boolean> Reverse sort order.
1350  \param s <boolean> Order ranges by their numerical sum.
1351 
1352  \returns <vector> With all elements sorted in ascending order.
1353  Returns \b undef when \p v is not defined or is not a vector.
1354 
1355  \details
1356 
1357  Elements are sorted using the \ref compare function. See its documentation
1358  for a description of the parameter \p s. To recursively sort all elements,
1359  set \p d greater than, or equal to, the maximum level of hierarchy in
1360  \p v.
1361 
1362  See [Wikipedia](https://en.wikipedia.org/wiki/Quicksort)
1363  for more information.
1364 *******************************************************************************/
1365 function qsort2
1366 (
1367  v,
1368  d = 0,
1369  r = false,
1370  s = true
1371 ) = not_defined(v) ? undef
1372  : !is_vector(v) ? undef
1373  : is_empty(v) ? empty_v
1374  : let
1375  (
1376  mp = v[floor(len(v)/2)],
1377 
1378  lt =
1379  [
1380  for (i = v)
1381  if (compare(mp, i, s) == -1)
1382  ((d > 0) && is_vector(i)) ? qsort2(i, d-1, r, s) : i
1383  ],
1384  eq =
1385  [
1386  for (i = v)
1387  if (compare(mp, i, s) == 0)
1388  ((d > 0) && is_vector(i)) ? qsort2(i, d-1, r, s) : i
1389  ],
1390  gt =
1391  [
1392  for (i = v)
1393  if (compare(mp, i, s) == +1)
1394  ((d > 0) && is_vector(i)) ? qsort2(i, d-1, r, s) : i
1395  ]
1396  )
1397  (r == true) ? concat(qsort2(gt, d, r, s), eq, qsort2(lt, d, r, s))
1398  : concat(qsort2(lt, d, r, s), eq, qsort2(gt, d, r, s));
1399 
1400 //----------------------------------------------------------------------------//
1401 // grow / reduce
1402 //----------------------------------------------------------------------------//
1403 
1404 //! Strip all matching values from an iterable value.
1405 /***************************************************************************//**
1406  \param v <vector> A vector of values.
1407  \param mv <value> A match value.
1408 
1409  \returns <vector> \p v with all elements equal to \p mv removed.
1410  Returns \b undef when \p v is not defined or is not iterable.
1411 *******************************************************************************/
1412 function strip
1413 (
1414  v,
1415  mv = empty_v
1416 ) = not_defined(v) ? undef
1417  : !is_iterable(v) ? undef
1418  : is_empty(v) ? empty_v
1419  : (first(v) == mv) ? concat(strip(ntail(v), mv))
1420  : concat(nfirst(v), strip(ntail(v), mv));
1421 
1422 //! Append a value to each element of an iterable value.
1423 /***************************************************************************//**
1424  \param nv <value> A new value to append.
1425  \param v <vector> A vector of values.
1426  \param r <boolean> Reduce vector element value before appending.
1427  \param j <boolean> Join each appendage as a vector.
1428  \param l <boolean> Append to last element.
1429 
1430  \returns <vector> With \p nv appended to each element of \p v.
1431  Returns \b undef when \p v is not defined or is not iterable.
1432 
1433  \details
1434 
1435  \b Example
1436  \code{.C}
1437  v1=[["a"], ["b"], ["c"], ["d"]];
1438  v2=[1, 2, 3];
1439 
1440  echo( eappend( v2, v1 ) );
1441  echo( eappend( v2, v1, r=false ) );
1442  echo( eappend( v2, v1, j=false, l=false ) );
1443  \endcode
1444 
1445  \b Result
1446  \code{.C}
1447  ECHO: [["a", 1, 2, 3], ["b", 1, 2, 3], ["c", 1, 2, 3], ["d", 1, 2, 3]]
1448  ECHO: [[["a"], 1, 2, 3], [["b"], 1, 2, 3], [["c"], 1, 2, 3], [["d"], 1, 2, 3]]
1449  ECHO: ["a", 1, 2, 3, "b", 1, 2, 3, "c", 1, 2, 3, "d"]
1450  \endcode
1451 
1452  \note Appending with reduction causes \p nv to be appended to the
1453  \e elements of each value of \p v that is a vector. Otherwise,
1454  \p nv is appended to the \e vector itself of each value of
1455  \p v that is a vector.
1456 *******************************************************************************/
1457 function eappend
1458 (
1459  nv,
1460  v,
1461  r = true,
1462  j = true,
1463  l = true
1464 ) = not_defined(v) ? undef
1465  : !is_iterable(v) ? undef
1466  : is_empty(v) ? ((j == true) ? [concat(nv)] : concat(nv))
1467  : let
1468  (
1469  ce = (r == true) ? first(v) : nfirst(v)
1470  )
1471  (len(v) == 1) ?
1472  (
1473  (j == true) ? (l == true) ? [concat(ce, nv)] : [ce]
1474  : (l == true) ? concat(ce, nv) : ce
1475  )
1476  : (j == true) ? concat([concat(ce, nv)], eappend(nv, ntail(v), r, j, l))
1477  : concat(concat(ce, nv), eappend(nv, ntail(v), r, j, l));
1478 
1479 //! Insert a new value into an iterable value.
1480 /***************************************************************************//**
1481  \param nv <value> A new value to insert.
1482  \param v <value> An iterable value.
1483 
1484  \param i <integer> An insert position index.
1485 
1486  \param mv <vector|string|value> Match value candidates.
1487  \param mi <integer> A match index.
1488 
1489  \param s <boolean> Use search for element matching (\b false uses find).
1490  \param si <integer> The element column index when matching.
1491 
1492  \returns <vector> With \p nv inserted into \p v at the specified position.
1493  Returns \b undef when no value of \p mv exists in \p v.
1494  Returns \b undef when <tt>(mi + 1)</tt> exceeds the matched
1495  element count.
1496  Returns \b undef when \p i does not map to an element of \p v.
1497  Returns \b undef when \p v is not defined or is not iterable.
1498 
1499  \details
1500 
1501  The insert position can be specified by an index, an element match value,
1502  or vector of potential match values (when using search). When multiple
1503  matches exists, \p mi indicates the insert position. When more than one
1504  insert position criteria is specified, the order of precedence
1505  is: \p mv, \p i.
1506 
1507  See find() for information on value matching.
1508 *******************************************************************************/
1509 function insert
1510 (
1511  nv,
1512  v,
1513  i = 0,
1514  mv,
1515  mi = 0,
1516  s = true,
1517  si
1518 ) = not_defined(v) ? undef
1519  : !is_iterable(v) ? undef
1520  : is_empty(v) ?
1521  (
1522  ( is_defined(mv) && any_equal(mv, empty_v)) ||
1523  (not_defined(mv) && (i == 0))
1524  ) ? concat(nv) : undef
1525  : ((i<0) || (i>len(v))) ? undef
1526  : let
1527  (
1528  p = is_defined(mv) ?
1529  (
1530  (s == false) ?
1531  find(mv, v, 0, si)[mi]
1532  : smerge(search(mv, v, 0, si), false)[mi]
1533  )
1534  : is_number(i) ? i
1535  : undef,
1536  h = (p>0) ? [for (j = [0 : p-1]) v[j]] : empty_v,
1537  t = (p>len(v)-1) ? empty_v : [for (j = [p : len(v)-1]) v[j]]
1538  )
1539  all_equal([h, t], empty_v) ? undef : concat(h, nv, t);
1540 
1541 //! Delete elements from an iterable value.
1542 /***************************************************************************//**
1543  \param v <value> An iterable value.
1544 
1545  \param i <range|vector|integer> Deletion Indexes.
1546 
1547  \param mv <vector|string|value> Match value candidates.
1548  \param mc <integer> A match count.
1549  For <tt>(mc>=1)</tt>, remove the first \p mc matches.
1550  For <tt>(mc<=0)</tt>, remove all matches.
1551 
1552  \param s <boolean> Use search for element matching (\b false uses find).
1553  \param si <integer> The element column index when matching.
1554 
1555  \returns <vector> \p v with all specified elements removed.
1556  Returns \b undef when \p i does not map to an element of \p v.
1557  Returns \b undef when \p v is not defined or is not iterable.
1558 
1559  \details
1560 
1561  The elements to delete can be specified by an index position, a vector
1562  of index positions, an index range, an element match value, or a vector
1563  of element match values (when using search). When \p mv is a vector of
1564  match values, all values of \p mv that exists in \p v are candidates
1565  for deletion. For each matching candidate, \p mc indicates the quantity
1566  to remove. When more than one deletion criteria is specified, the order
1567  of precedence is: \p mv, \p i.
1568 
1569  See find() for information on value matching.
1570 *******************************************************************************/
1571 function delete
1572 (
1573  v,
1574  i,
1575  mv,
1576  mc = 1,
1577  s = true,
1578  si
1579 ) = not_defined(v) ? undef
1580  : !is_iterable(v) ? undef
1581  : is_empty(v) ? empty_v
1582  : is_number(i) && ((i<0) || (i>(len(v)-1))) ? undef
1583  : is_vector(i) && ((min([for (y=i) y])<0) || (max([for (y=i) y])>(len(v)-1))) ? undef
1584  : is_range(i) && ((min([for (y=i) y])<0) || (max([for (y=i) y])>(len(v)-1))) ? undef
1585  : let
1586  (
1587  p = is_defined(mv) ?
1588  (
1589  (s == false) ?
1590  find(mv, v, mc, si)
1591  : smerge(search(mv, v, mc, si), false)
1592  )
1593  : is_number(i) ? [i]
1594  : is_vector(i) ? i
1595  : is_range(i) ? [for (y=i) y]
1596  : undef
1597  )
1598  [
1599  for (j = [0 : len(v)-1])
1600  if (is_empty(find(j, p))) v[j]
1601  ];
1602 
1603 //! Return the unique elements of an iterable value.
1604 /***************************************************************************//**
1605  \param v <value> An iterable value.
1606 
1607  \returns <vector> Of unique elements of \p v with order preserved.
1608  Returns \b undef when \p v is not defined or is not iterable.
1609 *******************************************************************************/
1610 function unique
1611 (
1612  v
1613 ) = not_defined(v) ? undef
1614  : !is_iterable(v) ? undef
1615  : is_empty(v) ? empty_v
1616  : (len(v) < 1) ? v
1617  // use exact element matching via s=false for find().
1618  : exists(last(v), nhead(v), s=false) ? unique(nhead(v))
1619  : concat(unique(nhead(v)), nlast(v));
1620 
1621 //! @}
1622 //! @}
1623 
1624 //----------------------------------------------------------------------------//
1625 // openscad-amu auxiliary scripts
1626 //----------------------------------------------------------------------------//
1627 
1628 /*
1629 BEGIN_SCOPE validate;
1630  BEGIN_SCOPE test;
1631  BEGIN_SCOPE g1;
1632  BEGIN_OPENSCAD;
1633  include <primitives.scad>;
1634  use <table.scad>;
1635  use <console.scad>;
1636  use <validation.scad>;
1637 
1638  show_passing = true; // show passing tests
1639  show_skipped = true; // show skipped tests
1640 
1641  echo( str("OpenSCAD Version ", version()) );
1642 
1643  // test-values columns
1644  test_c =
1645  [
1646  ["id", "identifier"],
1647  ["td", "description"],
1648  ["tv", "test value"]
1649  ];
1650 
1651  // test-values rows
1652  test_r =
1653  [
1654  ["t01", "The undefined value", undef],
1655  ["t02", "An odd integer", 1],
1656  ["t03", "An small even integer", 10],
1657  ["t04", "A large integer", 100000000],
1658  ["t05", "A small decimal (epsilon)", eps],
1659  ["t06", "The max number", number_max],
1660  ["t07", "The min number", number_min],
1661  ["t08", "The max number^2", number_max * number_max],
1662  ["t09", "The invalid number nan", 0 / 0],
1663  ["t10", "The boolean true", true],
1664  ["t11", "The boolean false", false],
1665  ["t12", "A character string", "a"],
1666  ["t13", "A string", "This is a longer string"],
1667  ["t14", "The empty string", empty_str],
1668  ["t15", "The empty vector", empty_v],
1669  ["t16", "A 1-tuple vector of undef", [undef]],
1670  ["t17", "A 1-tuple vector", [10]],
1671  ["t18", "A 3-tuple vector", [1, 2, 3]],
1672  ["t19", "A vector of vectors", [[1,2,3], [4,5,6], [7,8,9]]],
1673  ["t20", "A shorthand range", [0:9]],
1674  ["t21", "A range", [0:0.5:9]]
1675  ];
1676 
1677  test_ids = table_get_row_ids( test_r );
1678 
1679  // expected columns: ("id" + one column for each test)
1680  good_c = pmerge([concat("id", test_ids), concat("identifier", test_ids)]);
1681 
1682  // expected rows: ("golden" test results), use 's' to skip test
1683  t = true; // shortcuts
1684  f = false;
1685  u = undef;
1686  s = -1; // skip test
1687 
1688  good_r =
1689  [ // function 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21
1690  ["is_defined", f, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t],
1691  ["not_defined", t, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f],
1692  ["is_empty", f, f, f, f, f, f, f, f, f, f, f, f, f, t, t, f, f, f, f, f, f],
1693  ["is_scalar", t, t, t, t, t, t, t, t, t, t, t, f, f, f, f, f, f, f, f, s, s],
1694  ["is_iterable", f, f, f, f, f, f, f, f, f, f, f, t, t, t, t, t, t, t, t, s, s],
1695  ["is_string", f, f, f, f, f, f, f, f, f, f, f, t, t, t, f, f, f, f, f, f, f],
1696  ["is_vector", f, f, f, f, f, f, f, f, f, f, f, f, f, f, t, t, t, t, t, s, s],
1697  ["is_boolean", f, f, f, f, f, f, f, f, f, t, t, f, f, f, f, f, f, f, f, f, f],
1698  ["is_integer", f, t, t, t, f, t, t, f, f, f, f, f, f, f, f, f, f, f, f, f, f],
1699  ["is_decimal", f, f, f, f, t, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f],
1700  ["is_number", f, t, t, t, t, t, t, t, t, f, f, f, f, f, f, f, f, f, f, f, f],
1701  ["is_range", f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, t, t],
1702  ["is_nan", f, f, f, f, f, f, f, f, t, f, f, f, f, f, f, f, f, f, f, f, f],
1703  ["is_inf", f, f, f, f, f, f, f, t, f, f, f, f, f, f, f, f, f, f, f, f, f],
1704  ["is_even", s, f, t, t, f, t, t, s, s, s, s, s, s, s, s, s, s, s, s, s, s],
1705  ["is_odd", s, t, f, f, f, f, f, s, s, s, s, s, s, s, s, s, s, s, s, s, s]
1706  ];
1707 
1708  // sanity-test tables
1709  table_check( test_r, test_c, false );
1710  table_check( good_r, good_c, false );
1711 
1712  // validate helper function and module
1713  function get_value( vid ) = table_get(test_r, test_c, vid, "tv");
1714  module run_test( fname, fresult, vid )
1715  {
1716  value_text = table_get(test_r, test_c, vid, "td");
1717  pass_value = table_get(good_r, good_c, fname, vid);
1718 
1719  test_pass = validate( cv=fresult, t=pass_value, pf=true );
1720  test_text = validate( str(fname, "(", get_value(vid), ")=", pass_value), fresult, pass_value );
1721 
1722 
1723  if ( pass_value != s )
1724  {
1725  if ( !test_pass )
1726  log_warn( str(vid, "(", value_text, ") ", test_text) );
1727  else if ( show_passing )
1728  log_info( str(vid, " ", test_text) );
1729  }
1730  else if ( show_skipped )
1731  log_info( str(vid, " *skip*: '", fname, "(", value_text, ")'") );
1732  }
1733 
1734  // Indirect function calls would be very useful here!!!
1735  for (vid=test_ids) run_test( "is_defined", is_defined(get_value(vid)), vid );
1736  for (vid=test_ids) run_test( "not_defined", not_defined(get_value(vid)), vid );
1737  for (vid=test_ids) run_test( "is_empty", is_empty(get_value(vid)), vid );
1738  for (vid=test_ids) run_test( "is_scalar", is_scalar(get_value(vid)), vid );
1739  for (vid=test_ids) run_test( "is_iterable", is_iterable(get_value(vid)), vid );
1740  for (vid=test_ids) run_test( "is_string", is_string(get_value(vid)), vid );
1741  for (vid=test_ids) run_test( "is_vector", is_vector(get_value(vid)), vid );
1742  for (vid=test_ids) run_test( "is_boolean", is_boolean(get_value(vid)), vid );
1743  for (vid=test_ids) run_test( "is_integer", is_integer(get_value(vid)), vid );
1744  for (vid=test_ids) run_test( "is_decimal", is_decimal(get_value(vid)), vid );
1745  for (vid=test_ids) run_test( "is_number", is_number(get_value(vid)), vid );
1746  for (vid=test_ids) run_test( "is_range", is_range(get_value(vid)), vid );
1747  for (vid=test_ids) run_test( "is_nan", is_nan(get_value(vid)), vid );
1748  for (vid=test_ids) run_test( "is_inf", is_inf(get_value(vid)), vid );
1749  for (vid=test_ids) run_test( "is_even", is_even(get_value(vid)), vid );
1750  for (vid=test_ids) run_test( "is_odd", is_odd(get_value(vid)), vid );
1751 
1752  // end-of-tests
1753  END_OPENSCAD;
1754 
1755  BEGIN_MFSCRIPT;
1756  include --path "${INCLUDE_PATH}" {config_base,config_csg}.mfs;
1757  include --path "${INCLUDE_PATH}" script_std.mfs;
1758  END_MFSCRIPT;
1759  END_SCOPE;
1760 
1761  BEGIN_SCOPE g2;
1762  BEGIN_OPENSCAD;
1763  include <primitives.scad>;
1764  use <table.scad>;
1765  use <console.scad>;
1766  use <validation.scad>;
1767 
1768  show_passing = true; // show passing tests
1769  show_skipped = true; // show skipped tests
1770 
1771  echo( str("OpenSCAD Version ", version()) );
1772 
1773  // test-values columns
1774  test_c =
1775  [
1776  ["id", "identifier"],
1777  ["td", "description"],
1778  ["tv", "test value"]
1779  ];
1780 
1781  // test-values rows
1782  test_r =
1783  [
1784  ["t01", "The undefined value", undef],
1785  ["t02", "An odd integer", 1],
1786  ["t03", "The boolean true", true],
1787  ["t04", "The boolean false", false],
1788  ["t05", "A character string", "a"],
1789  ["t06", "A string", "This is a longer string"],
1790  ["t07", "The empty string", empty_str],
1791  ["t08", "The empty vector", empty_v],
1792  ["t09", "A shorthand range", [0:9]],
1793  ["t10", "A range", [0:0.5:9]],
1794  ["t11", "Test vector 01", [undef]],
1795  ["t12", "Test vector 02", [1]],
1796  ["t13", "Test vector 03", [1, 2, 3]],
1797  ["t14", "Test vector 04", [[1], [2], [3], [4], [5]]],
1798  ["t15", "Test vector 05", [[1,2], [2,3]]],
1799  ["t16", "Test vector 06", [[1,2], [2,3], [4,5], "ab"]],
1800  ["t17", "Test vector 07", [[1,2,3], [4,5,6], [7,8,9], ["a", "b", "c"]]],
1801  ["t18", "Test vector 08", [1, 2, 3, undef]],
1802  ["t19", "Test vector 09", [undef, undef, undef, undef]],
1803  ["t20", "Test vector 10", [[undef], [undef], [undef]]],
1804  ["t21", "Test vector 11", [true, true, true, true, false]],
1805  ["t22", "Test vector 12", [true, false, false, false, false]],
1806  ["t23", "Test vector 13", [true, true, true, true]]
1807  ];
1808 
1809  test_ids = table_get_row_ids( test_r );
1810 
1811  // expected columns: ("id" + one column for each test)
1812  good_c = pmerge([concat("id", test_ids), concat("identifier", test_ids)]);
1813 
1814  // expected rows: ("golden" test results), use 's' to skip test
1815  t = true; // shortcuts
1816  f = false;
1817  u = undef;
1818  s = -1; // skip test
1819 
1820  good_r =
1821  [ // function 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23
1822  ["all_equal_T", f, f, t, f, f, f, t, t, f, f, f, f, f, f, f, f, f, f, f, f, f, f, t],
1823  ["all_equal_F", f, f, f, t, f, f, t, t, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f],
1824  ["all_equal_U", t, f, f, f, f, f, t, t, f, f, t, f, f, f, f, f, f, f, t, f, f, f, f],
1825  ["any_equal_T", f, f, t, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, t, t, t],
1826  ["any_equal_F", f, f, f, t, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, t, t, f],
1827  ["any_equal_U", t, f, f, f, f, f, f, f, f, f, t, f, f, f, f, f, f, t, t, f, f, f, f],
1828  ["all_defined", f, t, t, t, t, t, t, t, t, t, f, t, t, t, t, t, t, f, f, t, t, t, t],
1829  ["any_undefined", t, f, f, f, f, f, f, f, f, f, t, f, f, f, f, f, f, t, t, f, f, f, f],
1830  ["all_scalars", u, t, t, t, f, f, s, s, s, s, t, t, t, f, f, f, f, t, t, f, t, t, t],
1831  ["all_vectors", u, f, f, f, f, f, t, t, f, f, f, f, f, t, t, f, t, f, f, t, f, f, f],
1832  ["all_strings", u, f, f, f, t, t, t, s, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f],
1833  ["all_numbers", u, t, f, f, f, f, s, s, f, f, f, t, t, f, f, f, f, f, f, f, f, f, f],
1834  ["all_len_1", u, f, f, f, t, t, s, s, f, f, f, f, f, t, f, f, f, f, f, t, f, f, f],
1835  ["all_len_2", u, f, f, f, f, f, s, s, f, f, f, f, f, f, t, t, f, f, f, f, f, f, f],
1836  ["all_len_3", u, f, f, f, f, f, s, s, f, f, f, f, f, f, f, f, t, f, f, f, f, f, f],
1837  ["almost_equal_AA", t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t],
1838  ["almost_equal_T", f, f, t, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f],
1839  ["almost_equal_F", f, f, f, t, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f],
1840  ["almost_equal_U", t, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f],
1841  ["compare_AA", t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t]
1842  ];
1843 
1844  // sanity-test tables
1845  table_check( test_r, test_c, false );
1846  table_check( good_r, good_c, false );
1847 
1848  // validate helper function and module
1849  function get_value( vid ) = table_get(test_r, test_c, vid, "tv");
1850  module run_test( fname, fresult, vid )
1851  {
1852  value_text = table_get(test_r, test_c, vid, "td");
1853  pass_value = table_get(good_r, good_c, fname, vid);
1854 
1855  test_pass = validate( cv=fresult, t="equals", ev=pass_value, pf=true );
1856  test_text = validate( str(fname, "(", get_value(vid), ")=", pass_value), fresult, "equals", pass_value );
1857 
1858  if ( pass_value != s )
1859  {
1860  if ( !test_pass )
1861  log_warn( str(vid, "(", value_text, ") ", test_text) );
1862  else if ( show_passing )
1863  log_info( str(vid, " ", test_text) );
1864  }
1865  else if ( show_skipped )
1866  log_info( str(vid, " *skip*: '", fname, "(", value_text, ")'") );
1867  }
1868 
1869  // Indirect function calls would be very useful here!!!
1870  for (vid=test_ids) run_test( "all_equal_T", all_equal(get_value(vid),t), vid );
1871  for (vid=test_ids) run_test( "all_equal_F", all_equal(get_value(vid),f), vid );
1872  for (vid=test_ids) run_test( "all_equal_U", all_equal(get_value(vid),u), vid );
1873  for (vid=test_ids) run_test( "any_equal_T", any_equal(get_value(vid),t), vid );
1874  for (vid=test_ids) run_test( "any_equal_F", any_equal(get_value(vid),f), vid );
1875  for (vid=test_ids) run_test( "any_equal_U", any_equal(get_value(vid),u), vid );
1876  for (vid=test_ids) run_test( "all_defined", all_defined(get_value(vid)), vid );
1877  for (vid=test_ids) run_test( "any_undefined", any_undefined(get_value(vid)), vid );
1878  for (vid=test_ids) run_test( "all_scalars", all_scalars(get_value(vid)), vid );
1879  for (vid=test_ids) run_test( "all_vectors", all_vectors(get_value(vid)), vid );
1880  for (vid=test_ids) run_test( "all_strings", all_strings(get_value(vid)), vid );
1881  for (vid=test_ids) run_test( "all_numbers", all_numbers(get_value(vid)), vid );
1882  for (vid=test_ids) run_test( "all_len_1", all_len(get_value(vid),1), vid );
1883  for (vid=test_ids) run_test( "all_len_2", all_len(get_value(vid),2), vid );
1884  for (vid=test_ids) run_test( "all_len_3", all_len(get_value(vid),3), vid );
1885  for (vid=test_ids) run_test( "almost_equal_AA", almost_equal(get_value(vid),get_value(vid)), vid );
1886  for (vid=test_ids) run_test( "almost_equal_T", almost_equal(get_value(vid),t), vid );
1887  for (vid=test_ids) run_test( "almost_equal_F", almost_equal(get_value(vid),f), vid );
1888  for (vid=test_ids) run_test( "almost_equal_U", almost_equal(get_value(vid),u), vid );
1889  for (vid=test_ids) run_test( "compare_AA", compare(get_value(vid),get_value(vid)) == 0, vid );
1890 
1891  // end-of-tests
1892  END_OPENSCAD;
1893 
1894  BEGIN_MFSCRIPT;
1895  include --path "${INCLUDE_PATH}" {config_base,config_csg}.mfs;
1896  include --path "${INCLUDE_PATH}" script_std.mfs;
1897  END_MFSCRIPT;
1898  END_SCOPE;
1899  END_SCOPE;
1900 
1901  BEGIN_SCOPE vector;
1902  BEGIN_OPENSCAD;
1903  include <primitives.scad>;
1904  use <table.scad>;
1905  use <console.scad>;
1906  use <validation.scad>;
1907 
1908  show_passing = true; // show passing tests
1909  show_skipped = true; // show skipped tests
1910 
1911  echo( str("OpenSCAD Version ", version()) );
1912 
1913  // test-values columns
1914  test_c =
1915  [
1916  ["id", "identifier"],
1917  ["td", "description"],
1918  ["tv", "test value"]
1919  ];
1920 
1921  // test-values rows
1922  test_r =
1923  [
1924  ["t01", "The undefined value", undef],
1925  ["t02", "The empty vector", empty_v],
1926  ["t03", "A range", [0:0.5:9]],
1927  ["t04", "A string", "A string"],
1928  ["t05", "Test vector 01", ["orange","apple","grape","banana"]],
1929  ["t06", "Test vector 02", ["b","a","n","a","n","a","s"]],
1930  ["t07", "Test vector 03", [undef]],
1931  ["t08", "Test vector 04", [[1,2],[2,3]]],
1932  ["t09", "Test vector 05", ["ab",[1,2],[2,3],[4,5]]],
1933  ["t10", "Test vector 06", [[1,2,3],[4,5,6],[7,8,9],["a","b","c"]]],
1934  ["t11", "Vector of integers 0 to 15", [for (i=[0:15]) i]]
1935  ];
1936 
1937  test_ids = table_get_row_ids( test_r );
1938 
1939  // expected columns: ("id" + one column for each test)
1940  good_c = pmerge([concat("id", test_ids), concat("identifier", test_ids)]);
1941 
1942  // expected rows: ("golden" test results), use 's' to skip test
1943  skip = -1; // skip test
1944 
1945  good_r =
1946  [ // function
1947  ["consts",
1948  empty_v, // t01
1949  empty_v, // t02
1950  empty_v, // t03
1951  empty_v, // t04
1952  empty_v, // t05
1953  empty_v, // t06
1954  empty_v, // t07
1955  empty_v, // t08
1956  empty_v, // t09
1957  empty_v, // t10
1958  empty_v // t11
1959  ],
1960  ["vstr",
1961  undef, // t01
1962  empty_str, // t02
1963  "[0 : 0.5 : 9]", // t03
1964  "A string", // t04
1965  "orangeapplegrapebanana", // t05
1966  "bananas", // t06
1967  "undef", // t07
1968  "[1, 2][2, 3]", // t08
1969  "ab[1, 2][2, 3][4, 5]", // t09
1970  "[1, 2, 3][4, 5, 6][7, 8, 9][\"a\", \"b\", \"c\"]", // t10
1971  "0123456789101112131415" // t11
1972  ],
1973  ["sum",
1974  undef, // t01
1975  0, // t02
1976  85.5, // t03
1977  undef, // t04
1978  undef, // t05
1979  undef, // t06
1980  undef, // t07
1981  [3,5], // t08
1982  undef, // t09
1983  [undef,undef,undef], // t10
1984  120 // t11
1985  ],
1986  ["find_12",
1987  empty_v, // t01
1988  empty_v, // t02
1989  empty_v, // t03
1990  empty_v, // t04
1991  empty_v, // t05
1992  empty_v, // t06
1993  empty_v, // t07
1994  [0], // t08
1995  [1], // t09
1996  empty_v, // t10
1997  empty_v // t11
1998  ],
1999  ["count_S1",
2000  0, // t01
2001  0, // t02
2002  0, // t03
2003  0, // t04
2004  0, // t05
2005  0, // t06
2006  0, // t07
2007  1, // t08
2008  1, // t09
2009  1, // t10
2010  1 // t11
2011  ],
2012  ["exists_S1",
2013  false, // t01
2014  false, // t02
2015  false, // t03
2016  false, // t04
2017  false, // t05
2018  false, // t06
2019  false, // t07
2020  true, // t08
2021  true, // t09
2022  true, // t10
2023  true // t11
2024  ],
2025  ["defined_or_D",
2026  "default", // t01
2027  empty_v, // t02
2028  [0:0.5:9], // t03
2029  "A string", // 04
2030  ["orange","apple","grape","banana"], // t05
2031  ["b","a","n","a","n","a","s"], // t06
2032  [undef], // t07
2033  [[1,2],[2,3]], // t08
2034  ["ab",[1,2],[2,3],[4,5]], // t09
2035  [[1,2,3],[4,5,6],[7,8,9],["a","b","c"]], // t10
2036  [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] // t11
2037  ],
2038  ["edefined_or_DE3",
2039  "default", // t01
2040  "default", // t02
2041  "default", // t03
2042  "t", // t04
2043  "banana", // t05
2044  "a", // t06
2045  "default", // t07
2046  "default", // t08
2047  [4,5], // t09
2048  ["a","b","c"], // t10
2049  3 // t11
2050  ],
2051  ["first",
2052  undef, // t01
2053  undef, // t02
2054  undef, // t03
2055  "A", // t04
2056  "orange", // t05
2057  "b", // t06
2058  undef, // t07
2059  [1,2], // t08
2060  "ab", // t09
2061  [1,2,3], // t10
2062  0 // t11
2063  ],
2064  ["second",
2065  undef, // t01
2066  undef, // t02
2067  undef, // t03
2068  " ", // t04
2069  "apple", // t05
2070  "a", // t06
2071  undef, // t07
2072  [2,3], // t08
2073  [1,2], // t09
2074  [4,5,6], // t10
2075  1 // t11
2076  ],
2077  ["last",
2078  undef, // t01
2079  undef, // t02
2080  undef, // t03
2081  "g", // t04
2082  "banana", // t05
2083  "s", // t06
2084  undef, // t07
2085  [2,3], // t08
2086  [4,5], // t09
2087  ["a","b","c"], // t10
2088  15 // t11
2089  ],
2090  ["nfirst_1",
2091  undef, // t01
2092  undef, // t02
2093  undef, // t03
2094  ["A"], // t04
2095  ["orange"], // t05
2096  ["b"], // t06
2097  [undef], // t07
2098  [[1,2]], // t08
2099  ["ab"], // t09
2100  [[1,2,3]], // t10
2101  [0] // t11
2102  ],
2103  ["nlast_1",
2104  undef, // t01
2105  undef, // t02
2106  undef, // t03
2107  ["g"], // t04
2108  ["banana"], // t05
2109  ["s"], // t06
2110  [undef], // t07
2111  [[2,3]], // t08
2112  [[4,5]], // t09
2113  [["a","b","c"]], // t10
2114  [15] // t11
2115  ],
2116  ["nhead_1",
2117  undef, // t01
2118  undef, // t02
2119  undef, // t03
2120  ["A"," ","s","t","r","i","n"], // t04
2121  ["orange","apple","grape"], // t05
2122  ["b","a","n","a","n","a"], // t06
2123  empty_v, // t07
2124  [[1,2]], // t08
2125  ["ab",[1,2],[2,3]], // t09
2126  [[1,2,3],[4,5,6],[7,8,9]], // t10
2127  [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14] // t11
2128  ],
2129  ["ntail_1",
2130  undef, // t01
2131  undef, // t02
2132  undef, // t03
2133  [" ","s","t","r","i","n","g"], // t04
2134  ["apple","grape","banana"], // t05
2135  ["a","n","a","n","a","s"], // t06
2136  empty_v, // t07
2137  [[2,3]], // t08
2138  [[1,2],[2,3],[4,5]], // t09
2139  [[4,5,6],[7,8,9],["a","b","c"]], // t10
2140  [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] // t11
2141  ],
2142  ["rselect_02",
2143  undef, // t01
2144  empty_v, // t02
2145  undef, // t03
2146  ["A"," ","s"], // t04
2147  ["orange","apple","grape"], // t05
2148  ["b","a","n"], // t06
2149  undef, // t07
2150  undef, // t08
2151  ["ab",[1,2],[2,3]], // t09
2152  [[1,2,3],[4,5,6],[7,8,9]], // t10
2153  [0,1,2] // t11
2154  ],
2155  ["eselect_F",
2156  undef, // t01
2157  empty_v, // t02
2158  undef, // t03
2159  ["A"," ","s","t","r","i","n","g"], // t04
2160  ["o","a","g","b"], // t05
2161  ["b","a","n","a","n","a","s"], // t06
2162  [undef], // t07
2163  [1,2], // t08
2164  ["a",1,2,4], // t09
2165  [1,4,7,"a"], // t10
2166  skip // t11
2167  ],
2168  ["eselect_L",
2169  undef, // t01
2170  empty_v, // t02
2171  undef, // t03
2172  ["A"," ","s","t","r","i","n","g"], // t04
2173  ["e","e","e","a"], // t05
2174  ["b","a","n","a","n","a","s"], // t06
2175  [undef], // t07
2176  [2,3], // t08
2177  ["b",2,3,5], // t09
2178  [3,6,9,"c"], // t10
2179  skip // t11
2180  ],
2181  ["eselect_1",
2182  undef, // t01
2183  empty_v, // t02
2184  undef, // t03
2185  skip, // t04
2186  ["r","p","r","a"], // t05
2187  skip, // t06
2188  [undef], // t07
2189  [2,3], // t08
2190  ["b",2,3,5], // t09
2191  [2,5,8,"b"], // t10
2192  skip // t11
2193  ],
2194  ["smerge",
2195  undef, // t01
2196  empty_v, // t02
2197  [[0:0.5:9]], // t03
2198  ["A string"], // t04
2199  ["orange","apple","grape","banana"], // t05
2200  ["b","a","n","a","n","a","s"], // t06
2201  [undef], // t07
2202  [1,2,2,3], // t08
2203  ["ab",1,2,2,3,4,5], // t09
2204  [1,2,3,4,5,6,7,8,9,"a","b","c"], // t10
2205  [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] // t11
2206  ],
2207  ["pmerge",
2208  undef, // t01
2209  empty_v, // t02
2210  undef, // t03
2211  ["A string"], // t04
2212  [
2213  ["o","a","g","b"],["r","p","r","a"],
2214  ["a","p","a","n"],["n","l","p","a"],
2215  ["g","e","e","n"]
2216  ], // t05
2217  [["b","a","n","a","n","a","s"]], // t06
2218  undef, // t07
2219  [[1,2],[2,3]], // t08
2220  [["a",1,2,4],["b",2,3,5]], // t09
2221  [[1,4,7,"a"],[2,5,8,"b"],[3,6,9,"c"]], // t10
2222  undef // t11
2223  ],
2224  ["reverse",
2225  undef, // t01
2226  empty_v, // t02
2227  undef, // t03
2228  ["g","n","i","r","t","s"," ","A"], // t04
2229  ["banana","grape","apple","orange"], // t05
2230  ["s","a","n","a","n","a","b"], // t06
2231  [undef], // t07
2232  [[2,3],[1,2]], // t08
2233  [[4,5],[2,3],[1,2],"ab"], // t09
2234  [["a","b","c"],[7,8,9],[4,5,6],[1,2,3]], // t10
2235  [15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0] // t11
2236  ],
2237  ["qsort",
2238  undef, // t01
2239  empty_v, // t02
2240  undef, // t03
2241  undef, // t04
2242  ["apple","banana","grape","orange"], // t05
2243  ["a","a","a","b","n","n","s"], // t06
2244  undef, // t07
2245  undef, // t08
2246  undef, // t09
2247  undef, // t10
2248  [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] // t11
2249  ],
2250  ["qsort2_HR",
2251  undef, // t01
2252  empty_v, // t02
2253  undef, // t03
2254  undef, // t04
2255  ["orange","grape","banana","apple"], // t05
2256  ["s","n","n","b","a","a","a"], // t06
2257  [undef], // t07
2258  [[3,2],[2,1]], // t08
2259  [[5,4],[3,2],[2,1],"ab"], // t09
2260  [["c","b","a"],[9,8,7],[6,5,4],[3,2,1]], // t10
2261  [15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0] // t11
2262  ],
2263  ["strip",
2264  undef, // t01
2265  empty_v, // t02
2266  undef, // t03
2267  ["A"," ","s","t","r","i","n","g"], // t04
2268  ["orange","apple","grape","banana"], // t05
2269  ["b","a","n","a","n","a","s"], // t06
2270  [undef], // t07
2271  [[1,2],[2,3]], // t08
2272  ["ab",[1,2],[2,3],[4,5]], // t09
2273  [[1,2,3],[4,5,6],[7,8,9],["a","b","c"]], // t10
2274  [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] // t11
2275  ],
2276  ["eappend_T0",
2277  undef, // t01
2278  [[0]], // t02
2279  undef, // t03
2280  [
2281  ["A",0],[" ",0],["s",0],["t",0],
2282  ["r",0],["i",0],["n",0],["g",0]
2283  ], // t04
2284  [
2285  ["orange",0],["apple",0],
2286  ["grape",0],["banana",0]
2287  ], // t05
2288  [
2289  ["b",0],["a",0],["n",0],["a",0],
2290  ["n",0],["a",0],["s",0]
2291  ], // t06
2292  [[undef,0]], // t07
2293  [[1,2,0],[2,3,0]], // t08
2294  [["ab",0],[1,2,0],[2,3,0],[4,5,0]], // t09
2295  [[1,2,3,0],[4,5,6,0],[7,8,9,0],["a","b","c",0]], // t10
2296  [
2297  [0,0],[1,0],[2,0],[3,0],[4,0],[5,0],
2298  [6,0],[7,0],[8,0],[9,0],[10,0],[11,0],
2299  [12,0],[13,0],[14,0],[15,0]
2300  ] // t11
2301  ],
2302  ["insert_T0",
2303  undef, // t01
2304  undef, // t02
2305  undef, // t03
2306  undef, // t04
2307  ["orange",0,"apple","grape","banana"], // t05
2308  ["b","a","n","a","n","a",0,"s"], // t06
2309  undef, // t07
2310  [[1,2],0,[2,3]], // t08
2311  ["ab",[1,2],0,[2,3],[4,5]], // t09
2312  undef, // t10
2313  [0,1,2,3,4,0,5,6,7,8,9,10,11,12,13,14,15] // t11
2314  ],
2315  ["delete_T0",
2316  undef, // t01
2317  empty_v, // t02
2318  undef, // t03
2319  ["A"," ","s","t","r","i","n","g"], // t04
2320  ["orange","grape","banana"], // t05
2321  ["b","a","n","a","n","a"], // t06
2322  [undef], // t07
2323  [[1,2]], // t08
2324  ["ab",[1,2],[4,5]], // t09
2325  [[1,2,3],[4,5,6],[7,8,9],["a","b","c"]], // t10
2326  [0,1,2,3,4,6,7,8,9,10,11,12,13,14,15] // t11
2327  ],
2328  ["unique",
2329  undef, // t01
2330  empty_v, // t02
2331  undef, // t03
2332  ["A"," ","s","t","r","i","n","g"], // t04
2333  ["orange","apple","grape","banana"], // t05
2334  ["b","a","n","s"], // t06
2335  [undef], // t07
2336  [[1,2],[2,3]], // t08
2337  ["ab",[1,2],[2,3],[4,5]], // t09
2338  [[1,2,3],[4,5,6],[7,8,9],["a","b","c"]], // t10
2339  [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] // t11
2340  ]
2341  ];
2342 
2343  // sanity-test tables
2344  table_check( test_r, test_c, false );
2345  table_check( good_r, good_c, false );
2346 
2347  // validate helper function and module
2348  function get_value( vid ) = table_get(test_r, test_c, vid, "tv");
2349  module run_test( fname, fresult, vid )
2350  {
2351  value_text = table_get(test_r, test_c, vid, "td");
2352  pass_value = table_get(good_r, good_c, fname, vid);
2353 
2354  test_pass = validate( cv=fresult, t="equals", ev=pass_value, pf=true );
2355  test_text = validate( str(fname, "(", get_value(vid), ")=", pass_value), fresult, "equals", pass_value );
2356 
2357  if ( pass_value != skip )
2358  {
2359  if ( !test_pass )
2360  log_warn( str(vid, "(", value_text, ") ", test_text) );
2361  else if ( show_passing )
2362  log_info( str(vid, " ", test_text) );
2363  }
2364  else if ( show_skipped )
2365  log_info( str(vid, " *skip*: '", fname, "(", value_text, ")'") );
2366  }
2367 
2368  // Indirect function calls would be very useful here!!!
2369 
2370  // create / convert
2371  for (vid=test_ids) run_test( "consts", consts(get_value(vid)), vid );
2372  for (vid=test_ids) run_test( "vstr", vstr(get_value(vid)), vid );
2373  for (vid=test_ids) run_test( "sum", sum(get_value(vid)), vid );
2374 
2375  // query
2376  for (vid=test_ids) run_test( "find_12", find([1,2],get_value(vid)), vid );
2377  for (vid=test_ids) run_test( "count_S1", count(1,get_value(vid),true), vid );
2378  for (vid=test_ids) run_test( "exists_S1", exists(1,get_value(vid),true), vid );
2379 
2380  // select
2381  for (vid=test_ids) run_test( "defined_or_D", defined_or(get_value(vid),"default"), vid );
2382  for (vid=test_ids) run_test( "edefined_or_DE3", edefined_or(get_value(vid),3,"default"), vid );
2383  for (vid=test_ids) run_test( "first", first(get_value(vid)), vid );
2384  for (vid=test_ids) run_test( "second", second(get_value(vid)), vid );
2385  for (vid=test_ids) run_test( "last", last(get_value(vid)), vid );
2386  for (vid=test_ids) run_test( "nfirst_1", nfirst(get_value(vid),n=1), vid );
2387  for (vid=test_ids) run_test( "nlast_1", nlast(get_value(vid),n=1), vid );
2388  for (vid=test_ids) run_test( "nhead_1", nhead(get_value(vid),n=1), vid );
2389  for (vid=test_ids) run_test( "ntail_1", ntail(get_value(vid),n=1), vid );
2390  for (vid=test_ids) run_test( "rselect_02", rselect(get_value(vid),i=[0:2]), vid );
2391  for (vid=test_ids) run_test( "eselect_F", eselect(get_value(vid),f=true), vid );
2392  for (vid=test_ids) run_test( "eselect_L", eselect(get_value(vid),l=true), vid );
2393  for (vid=test_ids) run_test( "eselect_1", eselect(get_value(vid),i=1), vid );
2394  // not tested: ciselect()
2395  // not tested: cmvselect()
2396 
2397  // reorder
2398  for (vid=test_ids) run_test( "smerge", smerge(get_value(vid)), vid );
2399  for (vid=test_ids) run_test( "pmerge", pmerge(get_value(vid)), vid );
2400  for (vid=test_ids) run_test( "reverse", reverse(get_value(vid)), vid );
2401  for (vid=test_ids) run_test( "qsort", qsort(get_value(vid)), vid );
2402  for (vid=test_ids) run_test( "qsort2_HR", qsort2(get_value(vid), d=5, r=true), vid );
2403 
2404  // grow / reduce
2405  for (vid=test_ids) run_test( "strip", strip(get_value(vid)), vid );
2406  for (vid=test_ids) run_test( "eappend_T0", eappend(0,get_value(vid)), vid );
2407  for (vid=test_ids) run_test( "insert_T0", insert(0,get_value(vid),mv=["x","r","apple","s",[2,3],5]), vid );
2408  for (vid=test_ids) run_test( "delete_T0", delete(get_value(vid),mv=["x","r","apple","s",[2,3],5]), vid );
2409  for (vid=test_ids) run_test( "unique", unique(get_value(vid)), vid );
2410 
2411  // end-of-tests
2412  END_OPENSCAD;
2413 
2414  BEGIN_MFSCRIPT;
2415  include --path "${INCLUDE_PATH}" {config_base,config_csg}.mfs;
2416  include --path "${INCLUDE_PATH}" script_std.mfs;
2417  END_MFSCRIPT;
2418  END_SCOPE;
2419 END_SCOPE;
2420 */
2421 
2422 //----------------------------------------------------------------------------//
2423 // end of file
2424 //----------------------------------------------------------------------------//
function defined_or(v, d)
Return a defined or default value.
function pmerge(v, j=true)
Parallel-merge vectors of iterable values.
function qsort(v, r=false)
Sort the numeric or string elements of a vector using quick sort.
function all_scalars(v)
Test if all elements of a value are scalars.
function nlast(v, n=1)
Return a vector containing the last n elements of an iterable value.
function all_strings(v)
Test if all elements of a value are strings.
function all_len(v, l)
Test if all elements of a value have a given length.
function eappend(nv, v, r=true, j=true, l=true)
Append a value to each element of an iterable value.
function almost_equal(v1, v2, p=4)
Test if all elements of two values are approximately equal.
function is_nan(v)
Test if a numerical value is invalid.
function is_decimal(v)
Test if a value is a decimal.
function is_even(v)
Test if a numerical value is even.
function second(v)
Return the second element of an iterable value.
function first(v)
Return the first element of an iterable value.
function is_iterable(v)
Test if a value has multiple parts and is iterable.
function is_integer(v)
Test if a value is an integer.
function sum(v, i1, i2)
Compute the sum of a vector of numbers.
function not_defined(v)
Test if a value is not defined.
function is_empty(v)
Test if an iterable value is empty.
function smerge(v, r=false)
Serial-merge vectors of iterable values.
function unique(v)
Return the unique elements of an iterable value.
function cmvselect(v, mv)
Case-like select a value from a vector of identified options by match-value.
function eselect(v, f=true, l=false, i)
Select an element from each iterable value.
function any_equal(v, cv)
Test if any element of a value equals a comparison value.
function nhead(v, n=1)
Return a vector containing all but the last n elements of an iterable value.
function is_boolean(v)
Test if a value is a boolean constant.
empty_v
A vector with no content (the empty vector).
Definition: constants.scad:79
function is_inf(v)
Test if a numerical value is infinite.
function delete(v, i, mv, mc=1, s=true, si)
Delete elements from an iterable value.
function any_undefined(v)
Test if any element of a value is undefined.
function is_string(v)
Test if a value is a string.
empty_str
A string with no content (the empty string).
Definition: constants.scad:76
function count(mv, v, s=true, i)
Count all occurrences of a match value in an iterable value.
function all_vectors(v)
Test if all elements of a value are vectors.
function reverse(v)
Reverse the elements of an iterable value.
function strip(v, mv=empty_v)
Strip all matching values from an iterable value.
function rselect(v, i)
Select a range of elements from an iterable value.
function edefined_or(v, i, d)
Return a defined vector element or default value.
function is_scalar(v)
Test if a value is a single non-iterable value.
function last(v)
Return the last element of an iterable value.
function is_odd(v)
Test if a numerical value is odd.
function find(mv, v, c=1, i, i1=0, i2)
Find the occurrences of a match value in an iterable value.
function all_defined(v)
Test if no element of a value is undefined.
function all_equal(v, cv)
Test if all elements of a value equal a comparison value.
function is_defined(v)
Test if a value is defined.
function is_vector(v)
Test if a value is a vector.
function consts(l, v)
Create a vector of constant elements.
function insert(nv, v, i=0, mv, mi=0, s=true, si)
Insert a new value into an iterable value.
function compare(v1, v2, s=true)
Compare any two values (may be iterable and/or of different types).
function is_range(v)
Test if a value is a range definition.
number_max
The largest representable number in OpenSCAD scripts.
Definition: constants.scad:70
function nfirst(v, n=1)
Return a vector containing the first n elements of an iterable value.
function exists(mv, v, s=true, i)
Check the existence of a match value in an iterable value.
function qsort2(v, d=0, r=false, s=true)
Hierarchically sort all elements of a vector using quick sort.
function ntail(v, n=1)
Return a vector containing all but the first n elements of an iterable value.
function all_numbers(v)
Test if all elements of a value are numbers.
function is_number(v)
Test if a value is a number.
function ciselect(v, i)
Case-like select a value from a vector of ordered options by index.
function vstr(v)
Convert all vector elements to strings and concatenate.