Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document ways of accessing numerical data #1328

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 33 additions & 6 deletions src/docs/sphinx/t_conduit_docs_tutorial_numeric_out.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Running main() from /Users/harrison37/Work/github/llnl/conduit/src/blt/thirdparty_builtin/googletest-master-2020-01-07/googletest/src/gtest_main.cc
[==========] Running 9 tests from 1 test suite.
Running main() from C:\Users\capps2\Documents\projects\axom\src\cmake\blt\thirdparty_builtin\googletest\googletest\src\gtest_main.cc
[==========] Running 12 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 9 tests from conduit_tutorial
[----------] 12 tests from conduit_tutorial
[ RUN ] conduit_tutorial.numeric_as_dtype
BEGIN_EXAMPLE("numeric_as_dtype")
100
Expand Down Expand Up @@ -35,6 +35,33 @@ my_vals[1] = 300
[100, 300]
END_EXAMPLE("numeric_strided_data_array")
[ OK ] conduit_tutorial.numeric_strided_data_array (0 ms)
[ RUN ] conduit_tutorial.numeric_data_accessor_start
BEGIN_EXAMPLE("numeric_data_accessor")
[ OK ] conduit_tutorial.numeric_data_accessor_start (0 ms)
[ RUN ] conduit_tutorial.numeric_data_accessor
int64 case:
[100.0, 300.0]
Some stats:
min: 100
max: 300
sum: 400
mean: 200
vals[0] = 100
vals[1] = 300
float64 case:
[2.2, 4.4, 6.6]
Some stats:
min: 2.2
max: 6.6
sum: 13.2
mean: 4.4
vals[0] = 2.2
vals[1] = 4.4
vals[2] = 6.6
[ OK ] conduit_tutorial.numeric_data_accessor (0 ms)
[ RUN ] conduit_tutorial.numeric_data_accessor_end
END_EXAMPLE("numeric_data_accessor")
[ OK ] conduit_tutorial.numeric_data_accessor_end (0 ms)
[ RUN ] conduit_tutorial.numeric_double_conversion_start
BEGIN_EXAMPLE("numeric_double_conversion")
[ OK ] conduit_tutorial.numeric_double_conversion_start (0 ms)
Expand Down Expand Up @@ -65,8 +92,8 @@ BEGIN_EXAMPLE("numeric_cxx11_init")
[1.0, 2.0, 3.0]
END_EXAMPLE("numeric_cxx11_init")
[ OK ] conduit_tutorial.numeric_cxx11_init (0 ms)
[----------] 9 tests from conduit_tutorial (0 ms total)
[----------] 12 tests from conduit_tutorial (2 ms total)

[----------] Global test environment tear-down
[==========] 9 tests from 1 test suite ran. (0 ms total)
[ PASSED ] 9 tests.
[==========] 12 tests from 1 test suite ran. (3 ms total)
[ PASSED ] 12 tests.
86 changes: 64 additions & 22 deletions src/docs/sphinx/tutorial_cpp_numeric.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ Accessing Numeric Data
=======================


Accessing Scalars and Arrays
--------------------------------

You can access leaf types (numeric scalars or arrays) using Node's *as_{type}*
methods.
methods. You can let Conduit handle striding with the DataArray class, and
additionally type conversion with the DataAccessor class.

Accessing Scalars
-----------------

The call to *Node::as_int64()* gives you the numeric value. Make sure the
Node does actually contain an int64, or Conduit will throw an error.

.. # from t_conduit_docs_tutorial_numeric: numeric_as_dtype

Expand All @@ -25,8 +29,9 @@ methods.
:start-after: BEGIN_EXAMPLE("numeric_as_dtype")
:end-before: END_EXAMPLE("numeric_as_dtype")

Or you can use Node::value(), which can infer the correct return type via a
cast.
Or you can use *Node::value()*, which can infer the correct return type via a
cast. As with the *as_{type}* methods, make sure to ask for the type of data
that the Node actually contains.

.. # from t_conduit_docs_tutorial_numeric: numeric_via_value

Expand All @@ -41,8 +46,14 @@ cast.
:end-before: END_EXAMPLE("numeric_via_value")


Accessing array data via pointers works the same way, using Node's *as_{type}*
methods.
Accessing Arrays
----------------

You can get numeric array data out of Conduit as a pointer; as a DataArray,
which handles striding; or as a DataAccessor, which handles striding and
type conversion.

Access array data via pointers using Node's *as_{type}* methods.

.. # from t_conduit_docs_tutorial_numeric: numeric_ptr_as_dtype

Expand Down Expand Up @@ -89,21 +100,10 @@ indexing for all types of arrays.
:start-after: BEGIN_EXAMPLE("numeric_strided_data_array")
:end-before: END_EXAMPLE("numeric_strided_data_array")

C++11 Initializer Lists
-----------------------------------

You can set Node values using C++11 style initializer lists of numeric literals.

.. literalinclude:: ../../tests/docs/t_conduit_docs_tutorial_numeric.cpp
:start-after: BEGIN_EXAMPLE("numeric_cxx11_init")
:end-before: END_EXAMPLE("numeric_cxx11_init")
:language: cpp
:dedent: 4


.. literalinclude:: t_conduit_docs_tutorial_numeric_out.txt
:start-after: BEGIN_EXAMPLE("numeric_cxx11_init")
:end-before: END_EXAMPLE("numeric_cxx11_init")
The DataAccessor class lets you write code to gracefully handle data
of varying type, such as user input data. See the next section for
an example of DataAccessor use.


Using Introspection and Conversion
Expand All @@ -127,3 +127,45 @@ double array.
:start-after: BEGIN_EXAMPLE("numeric_double_conversion")
:end-before: END_EXAMPLE("numeric_double_conversion")

Alternately, we can use a DataAccessor to do the conversion as needed.

.. # from t_conduit_docs_tutorial_numeric: numeric_data_accessor

.. literalinclude:: ../../tests/docs/t_conduit_docs_tutorial_numeric.cpp
:start-after: BEGIN_EXAMPLE("numeric_data_accessor")
:end-before: END_EXAMPLE("numeric_data_accessor")
:language: cpp
:dedent: 4

.. literalinclude:: t_conduit_docs_tutorial_numeric_out.txt
:start-after: BEGIN_EXAMPLE("numeric_data_accessor")
:end-before: END_EXAMPLE("numeric_data_accessor")

The first version examines the data type of the Node passed to
*process_doubles()* and converts the entire array if needed. The worker
function *must_have_doubles_function()* works with a pointer, as is the case
with much existing code, giving speed of access with no guard-rails. The second
version constructs a float64_accessor from its Node argument and passes that to
the worker function *takes_float64_accessor()*. That worker function shows how
to use the summary methods of DataAccessor and then prints the values in the
array passed to it. The DataAccessor casts each value as needed on access, thus
incurring a small cost at each access. The DataAccessor is also safer and
simpler to use.


C++11 Initializer Lists
-----------------------------------

You can set Node values using C++11 style initializer lists of numeric literals.

.. literalinclude:: ../../tests/docs/t_conduit_docs_tutorial_numeric.cpp
:start-after: BEGIN_EXAMPLE("numeric_cxx11_init")
:end-before: END_EXAMPLE("numeric_cxx11_init")
:language: cpp
:dedent: 4


.. literalinclude:: t_conduit_docs_tutorial_numeric_out.txt
:start-after: BEGIN_EXAMPLE("numeric_cxx11_init")
:end-before: END_EXAMPLE("numeric_cxx11_init")

64 changes: 64 additions & 0 deletions src/tests/docs/t_conduit_docs_tutorial_numeric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,70 @@ TEST(conduit_tutorial, numeric_strided_data_array)
END_EXAMPLE("numeric_strided_data_array");
}

//-----------------------------------------------------------------------------
TEST(conduit_tutorial, numeric_data_accessor_start)
{
BEGIN_EXAMPLE("numeric_data_accessor");
}

// _conduit_tutorial_cpp_numeric_data_accessor_start
//-----------------------------------------------------------------------------
void takes_float64_accessor(float64_accessor vals)
{
std::cout << "Some stats:\n\t min: " << vals.min() <<
"\n\t max: " << vals.max() <<
"\n\t sum: " << vals.sum() <<
"\n\t mean: " << vals.mean() <<
std::endl;
for(int i = 0; i < vals.number_of_elements(); i++)
{
std::cout << "vals[" << i << "] = " << vals[i] << std::endl;
}
}

//-----------------------------------------------------------------------------
void process_doubles_with_accessor(Node & n)
{
float64_accessor vals = n.value();
vals.print();
takes_float64_accessor(vals);
}

//-----------------------------------------------------------------------------
TEST(conduit_tutorial, numeric_data_accessor)
{
int64 i_vals[4] = {100,200,300,400};

Node n;
n.set(i_vals,2, // # of elements
0, // offset in bytes
sizeof(int64)*2); // stride in bytes

// Process values as float64, even though they're integers
std::cout << "int64 case: " << std::endl;
process_doubles_with_accessor(n);


float64 dvals[6] = {1.1,2.2,3.3,4.4,5.5,6.6};

Node dn;
dn.set(dvals,3, // # of elements
8, // offset in bytes
sizeof(float64)*2); // stride in bytes

// Process values as float64
std::cout << "float64 case: " << std::endl;
process_doubles_with_accessor(dn);
}
// _conduit_tutorial_cpp_numeric_data_accessor_end


//-----------------------------------------------------------------------------
TEST(conduit_tutorial, numeric_data_accessor_end)
{
END_EXAMPLE("numeric_data_accessor");
}

//-----------------------------------------------------------------------------
TEST(conduit_tutorial, numeric_double_conversion_start)
{
Expand Down
Loading