# This small test program demonstrates the different ways and different speeds
# of setting values in tcl3dVectors.
# See the description of the 4 SetMethod procedures below.

package require tcl3d

# Number of runs for each test method.
set runs 100

# Length of the tcl3dVector.
set len 1000

# Type of the elements of the tcl3dVector.
set type GLint

# Create the test vector.
set vec [tcl3dVector $type $len]

# Set the elements with the tcl3dVector object method "set".
# Most elegant way, but also the slowest. Only useful for small vectors.
proc SetMethod1 {} {
    global len vec

    for { set index 0 } { $index < $len } { incr index } {
        set val $index
        $vec set $index $val
    }
}

proc GetMethod1 {} {
    global len vec

    for { set index 0 } { $index < $len } { incr index } {
        set val $index
        if { [$vec get $index] != $val } {
            error "GetMethod1: Element value ([$vec get $index] at 
                   index $index incorrect"
        }
    }
}

# Set the elements with the tcl3dVector low-level function "setitem".
# Not so elegant, because you need to know the type of the vector,
# but much faster than method 1.
proc SetMethod2 {} {
    global len vec type

    for { set index 0 } { $index < $len } { incr index } {
        set val $index
        ${type}_setitem $vec $index $val
    }
}

proc GetMethod2 {} {
    global len vec type

    for { set index 0 } { $index < $len } { incr index } {
        set val $index
        if { [${type}_getitem $vec $index] != $val } {
            error "GetMethod2: Element value ([${type}_getitem $vec $index] at 
                   index $index incorrect"
        }
    }
}

# Set the elements with the new low level functions "tcl3dListToVector_TYPE".
# Not so elegant, because you need to know the type of the tcl3dVector
# and you have to build a Tcl list before setting the tcl3dVector.
# This is the fastest way.
proc SetMethod3 {} {
    global len vec fastCmd

    for { set index 0 } { $index < $len } { incr index } {
        set val $index
        lappend vecList $val
    }
    $fastCmd $vecList $vec $len
}

# Set the elements with the utility function "tcl3dVectorFromList",
# which internally calls the low level functions "tcl3dListToVector_TYPE".
# You don't have to care about allocating a tcl3dVector of approriate size.
# This should be only slightly slower than method3.
proc SetMethod4 {} {
    global len type

    for { set index 0 } { $index < $len } { incr index } {
        set val $index
        lappend vecList $val
    }
    set newVec [tcl3dVectorFromList $type $vecList]
    return $newVec
}

puts "Number of runs : $runs"
puts "Size of vectors: $len"
puts "Setting [expr $len*$runs] elements per method."

puts "SetMethod1: [time SetMethod1 $runs]"
puts "GetMethod1: [time GetMethod1 $runs]"

puts "SetMethod2: [time SetMethod2 $runs]"
puts "GetMethod2: [time GetMethod2 $runs]"

set fastCmd "tcl3dListToVector_$type"
if { [info commands $fastCmd] eq $fastCmd } {
    puts "SetMethod3: [time SetMethod3 $runs]"
    puts "GetMethod3: Not yet implemented."
} else {
    puts "$fastCmd only available in Tcl3D versions >= 0.3.3"
}

puts "SetMethod4: [time SetMethod4 $runs]"
puts "GetMethod4: Not yet implemented."

exit
