include <omdl-base.scad>;
    include <common/validation.scad>;
 
    echo( str("openscad version ", version()) );
 
    
    test_c =
    [
      ["id", "identifier"],
      ["td", "description"],
      ["tv", "test value"]
    ];
 
    
    test_r =
    [
      ["fac", "Function argument count",    undef
      ],
      ["crp", "Result precision",           undef
      ],
      ["t01", "All undefined",              [undef,undef,undef,undef,undef,undef]
      ],
      ],
      ["t03", "All scalars",                [60, 50, 40, 30, 20, 10]
      ],
      ["t04", "All 1d vectors",             [[99], [58], [12], [42], [15], [1]]
      ],
      ["t05", "All 2d vectors",             [
                                              [99,2], [58,16], [12,43],
                                              [42,13], [15,59], [1,85]
                                            ]
      ],
      ["t06", "All 3d vectors",             [
                                              [199,20,55], [158,116,75], [12,43,90],
                                              [42,13,34], [15,59,45], [62,33,69]
                                            ]
      ],
      ["t07", "All 4d vectors",             [
                                              [169,27,35,10], [178,016,25,20], [12,43,90,30],
                                              [42,13,34,60], [15,059,45,50], [62,33,69,40]
                                            ]
      ],
      ["t08", "Orthogonal vectors",         [
                                            ]
      ],
      ["t09", "Coplanar vectors",           [
                                            ]
      ]
    ];
 
 
    
    good_c = 
merge_p([concat(
"id", test_ids), concat(
"identifier", test_ids)]);
 
 
    
    skip = -1;  
 
    good_r =
    [ 
      ["distance_pp",
        2,                                                  
        4,                                                  
        undef,                                              
        undef,                                              
        undef,                                              
        undef,                                              
        43.3244,                                            
        106.2873,                                           
        undef,                                              
        1.4142,                                             
        1.4142                                              
      ],
      ["is_left_ppp",
        3,                                                  
        4,                                                  
        undef,                                              
        undef,                                              
        undef,                                              
        undef,                                              
        -463,                                               
        17009,                                              
        undef,                                              
        1,                                                  
        -3                                                  
      ],
      ["point_to_3d",
        1,                                                  
        4,                                                  
        undef,                                              
        undef,                                              
        undef,                                              
        undef,                                              
        [99,2,0],                                           
        [199,20,55],                                        
        undef,                                              
      ],
      ["line_dim",
        2,                                                  
        4,                                                  
        undef,                                              
        undef,                                              
        2,                                                  
        undef,                                              
        2,                                                  
        3,                                                  
        undef,                                              
        3,                                                  
        3                                                   
      ],
      ["line_tp",
        2,                                                  
        4,                                                  
        undef,                                              
        undef,                                              
        [60,50],                                            
        undef,                                              
        [58,16],                                            
        [158,116,75],                                       
        undef,                                              
      ],
      ["line_ip",
        2,                                                  
        4,                                                  
        undef,                                              
        undef,                                              
        undef,                                              
        [99,2],                                             
        [199,20,55],                                        
        undef,                                              
      ],
      ["vol_to_origin",
        2,                                                  
        4,                                                  
        undef,                                              
        undef,                                              
        [60,50],                                            
        undef,                                              
        [-41,14],                                           
        [-41,96,20],                                        
        undef,                                              
        [-1,1,0],                                           
        [-1,1,0]                                            
      ],
      ["dot_ll",
        4,                                                  
        4,                                                  
        undef,                                              
        undef,                                              
        3900,                                               
        undef,                                              
        -1650,                                              
        -5230,                                              
        undef,                                              
        1,                                                  
        0                                                   
      ],
      ["cross_ll",
        4,                                                  
        4,                                                  
        skip,                                               
        skip,                                               
        skip,                                               
        skip,                                               
        810,                                                
        [-4776,-1696,-1650],                                
        skip,                                               
        [-1,-1,1],                                          
        [0,0,4]                                             
      ],
      ["striple_lll",
        6,                                                  
        4,                                                  
        skip,                                               
        skip,                                               
        skip,                                               
        skip,                                               
        [-14760,5040],                                      
        -219976,                                            
        skip,                                               
        -2,                                                 
        0                                                   
      ],
      ["angle_ll",
        4,                                                  
        4,                                                  
        undef,                                              
        undef,                                              
        -2.9357,                                            
        undef,                                              
        153.8532,                                           
        134.4573,                                           
        undef,                                              
        60,                                                 
        90                                                  
      ],
      ["angle_lll",
        6,                                                  
        4,                                                  
        skip,                                               
        skip,                                               
        skip,                                               
        skip,                                               
        skip,                                               
        -91.362,                                            
        skip,                                               
        -63.4349,                                           
        0                                                   
      ],
      ["unit_l",
        2,                                                  
        4,                                                  
        undef,                                              
        undef,                                              
        [.7682,0.6402],                                     
        undef,                                              
        [-0.9464,0.3231],                                   
        [-0.3857,0.9032,0.1882],                            
        undef,                                              
        [-0.7071,0.7071,0],                                 
        [-0.7071,0.7071,0]                                  
      ],
      ["are_coplanar_lll",
        6,                                                  
        4,                                                  
        skip,                                               
        skip,                                               
        skip,                                               
        skip,                                               
        skip,                                               
        false,                                              
        skip,                                               
        false,                                              
        true                                                
      ],
      ["plane_to_normal",
        2,                                                  
        4,                                                  
        skip,                                               
        skip,                                               
        [60,50,0],                                          
        skip,                                               
        [0,0,1468],                                         
        [-4880,-6235,19924],                                
        skip,                                               
      ]
    ];
 
    
 
    
    function gv( vid, e ) = get_value( vid )[e];
    module log_test( m ) { 
log_type ( 
"test", m ); }
 
    module log_skip( f ) { log_test ( str("ignore: '", f, "'") ); }
    module run( fname, vid )
    {
 
        children();
      else
        log_test( str(vid, " -skip-: '", fname, "(", value_text, ")'") );
    }
    module test( fname, fresult, vid, pair )
    {
 
      test_pass = 
validate(cv=fresult, t=
"almost", ev=pass_value, p=comp_prcsn, pf=
true);
 
      farg_text = (pair == true)
      test_text = 
validate(str(fname, 
"(", farg_text, 
")=", pass_value), fresult, 
"almost", pass_value, comp_prcsn);
 
 
      if ( pass_value != skip )
      {
        if ( !test_pass )
          log_test( str(vid, " ", test_text, " (", value_text, ")") );
        else
          log_test( str(vid, " ", test_text) );
      }
      else
        log_test( str(vid, " -skip-: '", fname, "(", value_text, ")'") );
    }
 
    
    run_ids = delete( test_ids, mv=["fac", "crp"] );
 
    
    log_skip( "is_point()" );
    log_skip( "is_vector()" );
    log_skip( "is_line()" );
    log_skip( "is_vol()" );
    log_skip( "is_plane()" );
 
    
    for (vid=run_ids) run(
"distance_pp",vid) test( 
"distance_pp", 
distance_pp(gv(vid,0),gv(vid,1)), vid, 
false );
 
    log_skip( "distance_pl()" );
    log_skip( "distance_pn()" );
    for (vid=run_ids) run(
"is_left_ppp",vid) test( 
"is_left_ppp", 
is_left_ppp(gv(vid,0),gv(vid,1),gv(vid,2)), vid, 
false );
 
    log_skip( "point_closest_pl()" );
    log_skip( "point_closest_pn()" );
    for (vid=run_ids) run(
"point_to_3d",vid) test( 
"point_to_3d", 
point_to_3d(gv(vid,0)), vid, 
false );
 
    log_skip( "interpolate2d_l_pp()" );
 
    
 
    
    log_skip( "line2d_new()" );
    log_skip( "line3d_new()" );
    log_skip( "line_new()" );
    for (vid=run_ids) run(
"line_dim",vid) test( 
"line_dim", 
line_dim([gv(vid,0),gv(vid,1)]), vid, 
true );
 
    for (vid=run_ids) run(
"line_tp",vid) test( 
"line_tp", 
line_tp([gv(vid,0),gv(vid,1)]), vid, 
true );
 
    for (vid=run_ids) run(
"line_ip",vid) test( 
"line_ip", 
line_ip([gv(vid,0),gv(vid,1)]), vid, 
true );
 
    for (vid=run_ids) run(
"vol_to_origin",vid) test( 
"vol_to_origin", 
vol_to_origin([gv(vid,0),gv(vid,1)]), vid, 
true );
 
    log_skip( "vol_to_point()" );
    for (vid=run_ids) run(
"dot_ll",vid) test( 
"dot_ll", 
dot_ll([gv(vid,0),gv(vid,1)],[gv(vid,2),gv(vid,3)]), vid, 
true );
 
    for (vid=run_ids) run(
"cross_ll",vid) test( 
"cross_ll", 
cross_ll([gv(vid,0),gv(vid,1)],[gv(vid,2),gv(vid,3)]), vid, 
true );
 
    for (vid=run_ids) run(
"striple_lll",vid) test( 
"striple_lll", 
striple_lll([gv(vid,0),gv(vid,1)],[gv(vid,2),gv(vid,3)],[gv(vid,4),gv(vid,5)]), vid, 
true );
 
    for (vid=run_ids) run(
"angle_ll",vid) test( 
"angle_ll", 
angle_ll([gv(vid,0),gv(vid,1)],[gv(vid,2),gv(vid,3)]), vid, 
true );
 
    for (vid=run_ids) run(
"angle_lll",vid) test( 
"angle_lll", 
angle_lll([gv(vid,0),gv(vid,1)],[gv(vid,2),gv(vid,3)],[gv(vid,4),gv(vid,5)]), vid, 
true );
 
    for (vid=run_ids) run(
"unit_l",vid) test( 
"unit_l", 
unit_l([gv(vid,0),gv(vid,1)]), vid, 
true );
 
    for (vid=run_ids) run(
"are_coplanar_lll",vid) test( 
"are_coplanar_lll", 
are_coplanar_lll([gv(vid,0),gv(vid,1)],[gv(vid,2),gv(vid,3)],[gv(vid,4),gv(vid,5)]), vid, 
true );
 
 
    
    for (vid=run_ids) run(
"plane_to_normal",vid) test( 
"plane_to_normal", 
plane_to_normal([gv(vid,0),gv(vid,1)]), vid, 
true );
 
 
    
module log_type(t, m)
Output diagnostic message to console.
 
x_axis3d_uv
<vector-3d> The unit vector of the positive x-axis in 3d Euclidean space.
 
z_axis3d_uv
<vector-3d> The unit vector of the positive z-axis in 3d Euclidean space.
 
origin2d
<point-2d> The origin point coordinate in 2d Euclidean space.
 
origin3d
<point-3d> The origin point coordinate in 3-dimensional Euclidean space.
 
y_axis3d_uv
<vector-3d> The unit vector of the positive y-axis in 3d Euclidean space.
 
empty_lst
<list> A list with no values (the empty list).
 
function validate(d, cv, t, ev, p=4, pf=false)
Compare a computed test value with an known good result.
 
function line_tp(l)
Return the terminal point of a line or vector.
 
function dot_ll(l1, l2)
Compute the dot product of two lines or vectors in a 3d or 2d-space.
 
function are_coplanar_lll(l1, l2, l3, d=6)
Test if three lines or vectors are coplanar in 3d-space.
 
function angle_ll(l1, l2, s=true)
Compute the angle between two lines or vectors in a 3d or 2d-space.
 
function line_dim(l)
Return the number of dimensions of a line or vector.
 
function striple_lll(l1, l2, l3)
Compute the scalar triple product of three lines or vectors in a 3d or 2d-space.
 
function angle_lll(l1, l2, n)
Compute the angle between two lines or vectors in a 3d-space.
 
function vol_to_origin(l)
Convert line to vector by shifting it to the origin.
 
function point_to_3d(p)
Return 3d point unchanged or add a zeroed third dimension to 2d point.
 
function line_ip(l)
Return the initial point of a line or vector.
 
function cross_ll(l1, l2)
Compute the cross product of two lines or vectors in a 3d or 2d-space.
 
function is_left_ppp(p1, p2, p3)
Test if a point is left, on, or right of an infinite line in a 2d-space.
 
function unit_l(l)
Compute the normalized unit vector of a line or vector.
 
function plane_to_normal(n, cw=true)
Convert a planes' normal specification into a normal vector.
 
function distance_pp(p1, p2)
Compute the distance between two points.
 
function select_r(v, i)
Select a range of elements from an iterable value.
 
function append_e(nv, v, r=true, j=true, l=true)
Append a value to each element of an iterable value.
 
function sequence_ns(v, n=1, s=1, w=false)
Return a list of all n-element sequential-subsets of an iterable value.
 
function strl(v)
Convert a list of values to a concatenated string.
 
function merge_p(v, j=true)
Parallel-merge the iterable elements of a list.
 
module table_check(r, c, verbose=false)
Perform basic format checks on a table and output errors to console.
 
function table_get_row_ids(r)
Form a list of all table row identifiers.
 
function table_get_value(r, c, ri, ci)
Get the table cell value for a specified row and column identifier.