Does the Accellera SystemC Implementation incorrectly implement to_long()? - systemc

Consider the following SystemC code:
#include <iostream>
#include "systemc.h"
using namespace std;
int
sc_main(int argc, char* argv[])
{
sc_bv<3> foo;
operand_0 = "0d6";
cout << foo.to_long() << endl; // prints -2
return EXIT_SUCCESS;
}
This prints out -2 rather than 6 as I would have expected. The apparent reason for doing so would be that to_long() interprets the bit-vector 0b110 as signed. However, in IEEE Std 1666-2011, it says in Section 7.2.9 referring to integer conversion functions such as to_long():
These member functions shall interpret the bits within a SystemC integer,
fixed-point type or vector, or any part-select or concatenation thereof,
as representing an unsigned binary value, with the exception of signed
integers and signed fixed-point types.
Do I misunderstand something or is the SystemC implementation from Accellera not adhering to the standard in this aspect?

I think you are correct, there does seems to be a discrepancy between the SystemC LRM (IEEE Std 1666-2011) and the implementation.
If you want foo to be interpreted as an unsigned value, you must use to_ulong():
#include <iostream>
#include <systemc>
using namespace std;
int sc_main(int argc, char* argv[]) {
sc_bv<3> foo("0d6");
cout << foo.to_long() << endl; // prints -2
cout << foo.to_ulong() << endl; // prints 6
return EXIT_SUCCESS;
}

Related

g++ Static analysis: false positive with -fanalyzer?

Running this very little snippet, to show a problem I have with a much larger code:
// Type your code here, or load an example.
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
int main() {
auto res = make_unique<int>();
auto ptr = res.get();
if (ptr) {
*ptr = 5;
cout << *ptr << endl;
}
return 0;
}
with the -fanalyzer switch, I get a warning
warning: dereference of possibly-NULL 'operator new(4)' [CWE-690] [-Wanalyzer-possible-null-dereference]
But clearly I made all I could do to avoid this warning, but it is buried in the STL, which returns a unique_ptr with no validity control..
I understand the word "possibly" though..
Anyway to correct this on my side?
Update:
I made a mistake in the first go, now corrected
Update 2:
Even that code is refused
// Type your code here, or load an example.
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
int main() {
auto i = new int(3);
if (!i) {
return 1;
}
unique_ptr<int> res(i);
auto ptr = res.get();
if (!ptr) {
return 1;
}
*ptr = 5;
cout << *ptr << endl;
return 0;
}
Please, see here
As for now (gcc-12), the analyzer is not recommended for C++ code although work is underway to support it.
https://developers.redhat.com/articles/2022/04/12/state-static-analysis-gcc-12-compiler#toward_support_for_c__

How to copy a surface mesh in CGAL

I want to copy a mesh with the function copy_face_graph(source, target). But the target mesh is different (it has same number of vertices and faces, but the coordinates and the order are totally different).
The code:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <iostream>
#include <fstream>
#include <CGAL/boost/graph/copy_face_graph.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Surface_mesh<Kernel::Point_3> Mesh;
namespace PMP = CGAL::Polygon_mesh_processing;
int main(int argc, char* argv[]) {
const char* filename1 = (argc > 1) ? argv[1] : "data/blobby.off";
std::cout << ".off loaded" << std::endl;
std::ifstream input(filename1);
Mesh mesh_orig;
if (!input || !(input >> mesh_orig))
{
std::cerr << "First mesh is not a valid off file." << std::endl;
return 1;
}
input.close();
// ========================================================
Mesh mesh_copy;
CGAL::copy_face_graph(mesh_orig, mesh_copy);
// ========================================================
std::ofstream mesh_cpy("CPY_ANYLYZE/mesh_copy.off");
mesh_cpy << mesh_copy;
mesh_cpy.close();
return 0;
}
Dose anyone knows how to get a complete same mesh from the original mesh? Do I need add the named parameters, or maybe using another function?
Thanks a lot
Except if you intend to write some code working with different data structures, you can use the copy constructor from the Surface_mesh class, Mesh mesh_copy(mesh_orig). copy_face_graph does not do a raw copy because it works also if the input and output are of different types. However the output should be the same up to the order of the simplices.

How to set different decimal places in same rapidjson document

I have made a rapidjson document with all my objects and values using usual AddMember() method. Now I want to get the string out of that document for publishing to a mqtt broker. But inside that string, some members shall have 2 decimal places, some only one, and others all decimals.
I don't find how to set decimal place for a specific member after the document was fully builded.
I succeeded to do so by building my json document with a writer but this is not what i want to do because this document can't be easily modified:
#include <string>
#include <iostream>
#include <sstream>
#include <rapidjson/document.h> // rapidjson's DOM-style API
#include <rapidjson/prettywriter.h> // for stringify JSON
#include <rapidjson/stringbuffer.h>
using namespace rapidjson;
using namespace std;
int main (int argc, char* argv[])
{
Document doc;
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
writer.StartObject();
writer.Key("member1");
writer.SetMaxDecimalPlaces(2);
writer.Double(1.0000001);
writer.Key("member2");
writer.SetMaxDecimalPlaces(3);
writer.Double(3.123456);
writer.Key("member3");
writer.SetMaxDecimalPlaces(8);
writer.Double(2.123456);
writer.EndObject();
cout << buffer.GetString() << endl;
return 0;
}
./decimal
{"member1":1.0,"member2":3.123,"member3":2.123456}
Now, this how i build my document:
#include <string>
#include <iostream>
#include <sstream>
#include <rapidjson/document.h> // rapidjson's DOM-style API
#include <rapidjson/prettywriter.h> // for stringify JSON
#include <rapidjson/stringbuffer.h>
using namespace rapidjson;
using namespace std;
int main (int argc, char* argv[])
{
Document doc;
Document::AllocatorType& allocator = doc.GetAllocator();
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
doc.SetObject();
doc.AddMember("member1", 1.0000001, allocator);
doc.AddMember("member3", 3.123456, allocator);
doc.AddMember("member2", 2.123456, allocator);
writer.SetMaxDecimalPlaces(2);
doc.Accept(writer);
cout << buffer.GetString() << endl;
return 0;
}
./decimal
{"member1":1.0,"member2":2.12,"member3":3.12}
The SetMaxDecimalPlaces() applies to the whole document this way
I would like to get same output has first code example but using document made from second source code. How can i tell the writer to format each member differently ?
I'm super late to the party, but you can create a second writer with different writing settings:
StringBuffer buffer;
Writer<StringBuffer> writer1(buffer); // original writer
Writer<StringBuffer> writer2(buffer); // a new second writer
writer1.SetMaxDecimalPlaces(1);
writer2.SetMaxDecimalPlaces(2);
and then use the specific writers to write directly into the buffer instead of using the doc to call the writer:
writer.Key("member1");
writer.Double(1.0);
writer2.Key("member2");
writer2.Double(2.12);
writer2.Key("member3");
writer2.Double(3.12);
Full example:
using namespace rapidjson;
using namespace std;
int main (int argc, char* argv[])
{
StringBuffer buffer;
Writer<StringBuffer> writer1(buffer);
Writer<StringBuffer> writer2(buffer);
writer1.SetMaxDecimalPlaces(2);
writer2.SetMaxDecimalPlaces(2);
writer1.StartObject();
writer1.Key("member1");
writer1.Double(1.0);
writer2.Key("member2");
writer2.Double(2.12);
writer2.Key("member3");
writer2.Double(3.12);
writer1.EndObject();
cout << buffer.GetString() << endl;
return 0;
}

CGAL-4.8.1 Arrangements - Bezier Curves Save Arrangement to File Error

I am new to CGAL.
I tried to modify Examples/Arrangement_on_surfaces_2 Bezier_curves.cpp to save arrangement to file as shown below:
//! \file examples/Arrangement_on_surface_2/Bezier_curves.cpp
// Constructing an arrangement of Bezier curves.
#include <fstream>
#include <CGAL/basic.h>
#ifndef CGAL_USE_CORE
#include <iostream>
int main ()
{
std::cout << "Sorry, this example needs CORE ..." << std::endl;
return 0;
}
#else
#include <CGAL/Cartesian.h>
#include <CGAL/CORE_algebraic_number_traits.h>
#include <CGAL/Arr_Bezier_curve_traits_2.h>
#include <CGAL/Arrangement_2.h>
#include <CGAL/IO/Arr_iostream.h>
#include "arr_inexact_construction_segments.h"
#include "arr_print.h"
typedef CGAL::CORE_algebraic_number_traits Nt_traits;
typedef Nt_traits::Rational NT;
typedef Nt_traits::Rational Rational;
typedef Nt_traits::Algebraic Algebraic;
typedef CGAL::Cartesian<Rational> Rat_kernel;
typedef CGAL::Cartesian<Algebraic> Alg_kernel;
typedef Rat_kernel::Point_2 Rat_point_2;
typedef CGAL::Arr_Bezier_curve_traits_2<Rat_kernel, Alg_kernel, Nt_traits>
Traits_2;
typedef Traits_2::Curve_2 Bezier_curve_2;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
//typedef CGAL::Arrangement_2<Traits_2> Arrangement;
int main (int argc, char *argv[])
{
// Get the name of the input file from the command line, or use the default
// Bezier.dat file if no command-line parameters are given.
const char *filename = (argc > 1) ? argv[1] : "Bezier.dat";
const char *outfilename = (argc > 1) ? argv[1] : "BezierOut.dat";
// Open the input file.
std::ifstream in_file (filename);
if (! in_file.is_open()) {
std::cerr << "Failed to open " << filename << std::endl;
return 1;
}
// Read the curves from the input file.
unsigned int n_curves;
std::list<Bezier_curve_2> curves;
Bezier_curve_2 B;
unsigned int k;
in_file >> n_curves;
for (k = 0; k < n_curves; k++) {
// Read the current curve (specified by its control points).
in_file >> B;
curves.push_back (B);
std::cout << "B = {" << B << "}" << std::endl;
}
in_file.close();
// Construct the arrangement.
Arrangement_2 arr;
insert (arr, curves.begin(), curves.end());
// Print the arrangement size.
std::ofstream out_file;
out_file.open(outfilename);
out_file << "The arrangement size:" << std::endl
<< " V = " << arr.number_of_vertices()
<< ", E = " << arr.number_of_edges()
<< ", F = " << arr.number_of_faces() << std::endl;
out_file << arr;
out_file.close();
return 0;
}
#endif
If I comment out the line out_file << arr; it works fine. Otherwise it generates a C2678 error in read_x_monotone_curve in Arr_text_formtter.h
I am using Visual Studio 15 x86.
Thank you for any help.
I solve this by modifying the print_arrangement(arr) routine in arr_print.h to save_arrangement(arr) with a std::ofstream in place of std::cout.
It appears that the << operator does not work.
If someone else has a better solution I am open to it.
Points of intersections in an arrangement of Bezier curves cannot be represented in an exact manner. Therefore, such an arrangement cannot be saved using the default export (<<) operator and the standard format.
The easiest solution is to store the curves, but this means that the arrangement must be recomputed each time the curves are read. Perhaps other solution could be devised, but they are not implemented.

what's the storage format of protobuf data?

the .proto file:
package lm;
message helloworld
{
required int32 id = 1;
required string str = 2;
optional int32 opt = 3;
}
the writer.cc file:
#include <iostream>
#include <string>
#include "lm.helloworld.pb.h"
#include <fstream>
using namespace std;
int main()
{
lm::helloworld msg1;
msg1.set_id(101000);
msg1.set_str("helloworld,this is a protobuf writer");
fstream output("log", ios::out | ios::trunc | ios::binary);
string _data;
msg1.SerializeToString(&_data);
cout << _data << endl;
if(!msg1.SerializeToOstream(&output))
{
cerr << "Failed to write msg" << endl;
return -1;
}
return 0;
}
the reader.cc file:
#include <iostream>
#include <fstream>
#include <string>
#include "lm.helloworld.pb.h"
using namespace std;
void ListMsg(const lm::helloworld & msg)
{
cout << msg.id() << endl;
cout << msg.str() << endl;
}
int main(int argc, char* argv[])
{
lm::helloworld msg1;
{
fstream input("log", ios::in | ios::binary);
if (!msg1.ParseFromIstream(&input))
{
cerr << "Failed to parse address book." << endl;
return -1;
}
}
ListMsg(msg1);
return 0;
}
It's a simple reader and writer model using protobuf. but what's in the log is a readable string a typed in the write.cc file instead of "numeric format",why is that?
The encoding is described here.
Without an example of what comes out the other end, that is slightly hard to answer precisely, but there are two possible explanations of what you are seeing:
you have explicitly switched into TextFormat in your code; this is very unlikely - and indeed, the primary use of TextFormat is debugging etc
far more likely, you're just seeing the text data from your message in the binary; text is encoded as UTF-8, so if you open a protobuf file in a text editor, pieces of it will appear readable enough to display something in the file
The real question is: what are the actual bytes in your output file? If it is something like:
08-88-95-06-12-24-68-65-6C-6C-6F-77-6F-72-6C-64-2C-74-68-69-73-20-69-73-20-61-20-70-72-6F-74-6F-62-75-66-20-77-72-69-74-65-72
then that is the binary format; but note that most of that is simply the UTF-8 of the string "helloworld,this is a protobuf writer" - which dominates the message by sheer size:
68-65-6C-6C-6F-77-6F-72-6C-64-2C-74-68-69-73-20-69-73-20-61-20-70-72-6F-74-6F-62-75-66-20-77-72-69-74-65-72
So if you look in any text editor, it will appear as a few garbled characters at the start followed by the clearly legible helloworld,this is a protobuf writer.
The "binary" here is the bit at the start:
08-88-95-06-12-24
This is:
08: header: field 1, varint
88-95-06: the value (decimal) 101000 as a varint
12: header: field 2, length-prefixed
24: the value (decimal) 36 as a varint (the length of the string, in bytes)
The key points to note:
if your message is dominated by text, the yes, large parts of it will look human-readable even in binary form
look at the overheads; it to 6 bytes to encode the entire rest of the message, and 3 bytes of that was data (the 101000) - so only 3 bytes was actually lost as overhead; now compare and contrast to xml, json, etc to understand what protobuf is doing to help you