5. Scalar¶
[v0.7+][C++ only]
Scalar is a generic data type which can hold various data types in C++.
In Python, the data type of any variable is dynamic, i.e. it can be changed at any time. In contrast to this, C++ data types are static and cannot be changed once they are declared. In the C++/Python cross-platform library Cytnx, we provide a generic data type Scalar on the C++ side which allows variables to be used like dynamic data types in Python, with all the convenience and advantages related to this.
5.1. Define/Declare a Scalar¶
Defining a Scalar is straight forward. One can convert directly from a supported standard C++ Type to a Scalar.
Currently, the following standard C++ data types are supported by Cytnx Scalar:
Cytnx type |
C++ type |
Type object |
|---|---|---|
cytnx_double |
double |
Type.Double |
cytnx_float |
float |
Type.Float |
cytnx_uint64 |
uint64_t |
Type.Uint64 |
cytnx_uint32 |
uint32_t |
Type.Uint32 |
cytnx_uint16 |
uint16_t |
Type.Uint16 |
cytnx_int64 |
int64_t |
Type.Int64 |
cytnx_int32 |
int32_t |
Type.Int32 |
cytnx_int16 |
int16_t |
Type.Int16 |
cytnx_complex128 |
std::complex<double> |
Type.ComplexDouble |
cytnx_complex64 |
std::complex<float> |
Type.ComplexFloat |
cytnx_bool |
bool |
Type.Bool |
Consider the example where we want to create a Scalar with double type. The conversion between C++ standard type to Scalar is very flexible, depending on the application scenario:
Convert from a C++ variable
1double cA = 1.33;
2Scalar A(cA);
3cout << A << endl;
Output >>
< 1.33 > dtype: [Double (Float64)]
Create directly:
1Scalar A(double(1.33));
2
3Scalar A2 = double(1.33);
4
5Scalar A3(10, Type.Double);
6
7cout << A << A2 << A3 << endl;
Output:
< 1.33 > dtype: [Double (Float64)]< 1.33 > dtype: [Double (Float64)]< 10 > dtype: [Double (Float64)]
Note
We can also just assign a C++ type to Scalar as in the case of A2.
In the case of variable A3, the assigned value 10 by default in C++ is an integer type. If we want the Scalar to be of type double, we can pass an additional dtype to further specify the type explicitly.
Convert to a C++ data type:
Converting to a C++ data type works just like other type castings in C++:
1Scalar A = 10;
2cout << A << endl;
3
4auto fA = float(A); // convert to float
5cout << typeid(fA).name() << fA << endl;
6
7// convert to complex double
8auto cdA = complex128(A);
9cout << cdA << endl;
10
11// convert to complex float
12auto cfA = complex64(A);
13cout << cfA << endl;
Output:
< 10 > dtype: [Int32]
f10
(10,0)
(10,0)
Note
Note the slightly different syntax in case of complex type castings. Use complex128() and complex64() to convert to a standard C++ type complex<double> and complex<float> respectively.
5.2. Change data type¶
To change the data type of a Scalar, use .astype().
1Scalar A(1.33);
2cout << A << endl;
3
4A = A.astype(Type.Float);
5cout << A << endl;
Output:
< 1.33 > dtype: [Double (Float64)]
< 1.33 > dtype: [Float (Float32)]
5.3. Application scenarios¶
The Scalar type allows for many possibilities in C++ that are otherwise hard to achieve. We will consider some examples in the following.
If we want to have a list (vector) with elements having different data types, we can use tuple objects in C++. However, that requires the number of elements and data types to be known and fixed a priori. Using Scalar, we can also create a vector with a variable number of elements and variable data types:
1vector<Scalar> out;
2
3out.push_back(Scalar(1.33)); // double
4out.push_back(Scalar(10)); // int
5out.push_back(Scalar(cytnx_complex128(3, 4))); // complex double
6
7cout << out[0] << out[1] << out[2] << endl;
Output:
< 1.33 > dtype: [Double (Float64)]< 10 > dtype: [Int32]< (3,4) > dtype: [Complex Double (Complex Float64)]
In C++, unlike Python, we can not create a function that can take arbitrary types of arguments. This becomes possible with Scalar:
1Scalar generic_func(const std::vector<Scalar> &args){
2 // do something here with args
3
4}
This way, the user can dynamically decide which types of variables to pass to the function.