Annoying, transitive-const-ness issue in D - constants

I'm running across a very annoying problem regarding transitive const in D.
I have the code below:
struct Slice(T)
{
T items;
size_t start, length, stride;
this(T items, size_t start = 0, size_t length = size_t.max, size_t stride=1)
{
if (length == size_t.max)
{ length = 1 + (items.length - start - 1) / stride; }
this.items = items;
this.start = start;
this.length = length;
this.stride = stride;
}
Slice!(T) opSlice(size_t a, size_t b)
{
// Everything is fine here
return Slice!(T)(items, start + a * stride, b - a, stride);
}
const(Slice!(T)) opSlice(size_t a, size_t b) const
{
// ERROR! 'items' is const(T), not T.
return const(Slice!(T))(items, start + a * stride, b - a, stride);
}
}
The trouble I'm running to is that, pretty much, the data types const(Slice!int) and Slice!const(int) and const(Slice!const(int)) are just... weird.
How do I overload opSlice above, to return a constant copy of the current slice which can subsequently be used like the original slice?
In other words, let's say I have:
void test(in Slice!(int[]) some_slice)
{
//...
}
void main()
{
auto my_slice = Slice!(int[])();
const my_const_slice = my_slice;
test(my_slice); // succeeds
test(my_const_slice); //succeeds
test(my_const_slice[0 .. 1]); // fails
}
The code above doesn't work. What is the best way of making it work? (I could of course always templatize test(), but then all the slice variations -- const(Slice!(Slice!const(int[]))) and such -- would grow exponentially, and confusingly so.)
Edit:
Is there a solution that works for structs and classes?

change the constructor to
inout this(inout T items, size_t start = 0, size_t length = size_t.max, size_t stride=1)
{
if (length == size_t.max)
{ length = 1 + (items.length - start - 1) / stride; }
this.items = items;
this.start = start;
this.length = length;
this.stride = stride;
}
the inout keyword was made for this, it lets the const-ness/immutability of a parameter propagate to the result

inout also works if Slice is a class:
class Slice(T)
{
T items;
size_t start, length, stride;
this(){}
inout this(inout T items, size_t start = 0, size_t length = size_t.max, size_t stride=1)
{
if (length == size_t.max)
{ length = 1 + (items.length - start - 1) / stride; }
this.items = items;
this.start = start;
this.length = length;
this.stride = stride;
}
inout(Slice!(T)) opSlice(size_t a, size_t b) inout{
return new inout(Slice!T)(items, start + a * stride, b - a, stride);
}
}
void test(in Slice!(int[]) some_slice)
{
//...
}
void main()
{
auto my_slice = new Slice!(int[])();
const my_const_slice = my_slice;
test(my_slice); // succeeds
test(my_const_slice);//succeeds
test(my_const_slice[0 .. 1]); // succeeds
}

Related

mergsort printing a strange result

I am having an issue with my merge sort, when I print out my sortedArray it only returns [ 0.0, 0.0.....] Im not sure if there is an error in my sort code or in my print line or if it has to do with doubles. The code I am us posted below.
By calling System.out.println(toString(sortedArray) I get an even more obscure answer.
Thanks for any help.
package mergesort;
import java.util.Arrays;
import java.util.Random;
public class mergesort {
public static void main(String[] args) {
double[] array = getIntArray();
long before = System.nanoTime();
double[] sortedArray= mergeSort(array);
System.out.println("Sorting took "+ (System.nanoTime() - before) +" nanoseconds ");
System.out.println(toString(array) + "\n\n" + toString(sortedArray) + "\n main method completed in: " + (System.nanoTime() - before) + " nanoseconds.");
}
private static String toString(double[] array) {
StringBuilder sb = new StringBuilder("[ ");
double len = array.length;
for(int i = 0; i < len - 1; i++) {
sb.append(array[i] + ", ");
}
sb.append(array[(int) (len - 1)] + " ]");
return sb.toString();
}
public static double[] mergeSort(double[] array) {
if (array.length <= 1) {
return array;
}
int half = array.length / 2;
return merge(mergeSort(Arrays.copyOfRange(array, 0, half)),
mergeSort(Arrays.copyOfRange(array, half, array.length)));
}
private static double[] merge(double[] ds, double[] ds2) {
int len1 = ds.length, len2 = ds2.length;
int totalLength = len1 + len2;
double[] result = new double[totalLength];
int counterForLeft =0,counterForRight=0,resultIndex=0;
while(counterForLeft<len1 || counterForRight < len2){
if(counterForLeft<len1 && counterForRight < len2){
if(ds[counterForLeft]<= ds2[counterForRight]){
result[resultIndex++] =(int) ds[counterForLeft++];
} else {
result[resultIndex++] =(int) ds2[counterForRight++];
}
}else if(counterForLeft<len1){
result[resultIndex++] = (int) ds[counterForLeft++];
}else if (counterForRight <len2){
result[resultIndex++] =(int) ds2[counterForRight++];
}
}
return result;
}
private static double[] getIntArray() {
double[] array = new double[10000];
Random random = new Random();
for(int i = 0; i < 10000; i++) {
array[i] = (random.nextDouble() * .99999);
}
return array;
}
}
In the merge method, when copying from one of the input arrays to the results, you cast to int. For example:
result[resultIndex++] =(int) ds[counterForLeft++];
All your doubles are in the range [0...1), so the result of casting any of them to int is zero. Just get rid of those casts, and you will keep your numbers in the merge result.
As an additional tip, it is much easier to debug small problems than large ones. It failed for any size greater than 2, so you should have been debugging with size 2, not 10000.

Why am I getting this dynamic IndexOutOfBounds Exception?

I am trying to write a program where text is translated into hexadecimal, then into decimal, and then into an (R, G, B) format. However, when trying to incorporate ClickableRectangle, I get an ArrayIndexOutOfBounds exception that changes dynamically with the sign of rects.
Any thoughts on my problem/optimization?
char[] colors; //Array of characters to be translated into hexadecimal
String r = ""; //Red value of color
String g = ""; //Green value of color
String b = ""; //Blue value of color
int x = 0; //X-coordinate of rectangle
int y = 0; //Y-coordinate of rectangle
int q; //Character count
ClickableRectangle[] rects = new ClickableRectangle[400*400]; //Rectangles
void settings() {
size(displayWidth, displayHeight);
}
void setup() {
background(0);
colors = new char[3];
String s = ([INSERT TRANSCRIPT HERE]); //Too long to be in post//
for (int i = 0; i < s.length(); i+=3) {
for (int j = i; j < i+3; j++) {
colors[j-i] = s.charAt(j);
}
r = hex(colors[0], 2);
g = hex(colors[1], 2);
b = hex(colors[2], 2);
drawAPoint(r, g, b, i);
println(i);
q++;
}
save("SlachtochtFeuf.png"); //Ignore this, using for testing purposes
println("q = " + q);
println("x = " + x);
println("y = " + y);
}
void draw() {
for (int i = 0; i < rects.length; i++) {
if (rects[i].isClicked()) {
println(rects[i].getValue()); //Prints char representation of color
}
}
}
void drawAPoint(String r2, String g2, String b2, int i) {
noStroke();
fill(unhex(r2), unhex(g2), unhex(b2));
rects[i] = new ClickableRectangle(x, y, r2, g2, b2);
rects[i].display();
if (x >= width) {
x = 0;
y += 6;
} else {
x+=6;
}
}
class ClickableRectangle {
int x = 0;
int y = 0;
String r = "";
String g = "";
String b = "";
public ClickableRectangle(int x, int y, String r, String g, String b) {
this.x = x;
this.y = y;
this.r = r;
this.g = g;
this.b = b;
}
public void display() {
fill(unhex(r), unhex(g), unhex(b));
rect(x, y, 6, 6);
}
public void setRGB(String r, String g, String b) {
this.r = r;
this.g = g;
this.b = b;
}
public String getValue() {
return ""+char(unhex(r))+char(unhex(g))+char(unhex(b));
}
public boolean isClicked() {
return mouseX > x && mouseY > y && mouseX < x+6 && mouseY < y+6;
}
}
For future reference, you should tell us exactly which line throws the exception, and you should include all of the code needed to repeat the problem. If the text is too long to post, then narrow it down to a smaller MCVE.
But judging from what I can see, the problem appears to be here:
String s = "test";
for (int i = 0; i < s.length(); i+=3) {
for (int j = i; j < i+3; j++) {
colors[j-i] = s.charAt(j);
}
//other stuff
}
Just run through this in your head:
When i=0 and j=0, you access charAt 0.
When i=0 and j=1, you access charAt 1.
When i=0 and j=2, you access charAt 2.
When i=3 and j=3, you access charAt 3.
When i=3 and j=4, you access charAt 4.
You could also use println() statements to better see what's going on:
for (int i = 0; i < s.length(); i+=3) {
println("i: " + i);
for (int j = i; j < i+3; j++) {
println("j: " + j);
colors[j-i] = s.charAt(j);
}
//other stuff
}
That prints out:
i: 0
j: 0
j: 1
j: 2
0
i: 3
j: 3
j: 4
That last part is the problem- the String I'm using is "test", so it only has 4 characters: charAt(0), charAt(1), charAt(2), and charAt(3). So when you try to access charAt(4), it throws a StringIndexOutOfBoundsException!
I don't know exactly what you're trying to do here, but you'll have to rework your code so that it doesn't try to access characters outside the bounds of the String.
As a side note: it looks like you're trying to code your whole project all at once. Don't do that. Instead, develop this in small increments- try to get smaller pieces working by themselves before you combine them into your whole project. Can you write a separate sketch that simply loops over a String and prints out the characters you're trying to extract? Then if you get stuck, you can use that smaller sketch as your MCVE, and it'll be easier for us to help you.

Overloading Operator Rational Error

So I have looked around because this seems to be a common homework problem for most C++ students, but I can't seem to find one that will answer my issue. I feel that I have filled out the code correctly but I get the same error each time.
Here is my code:
#include <iostream>
using namespace std;
class Rational
{
public:
Rational() {
num = 0;
denom = 1;
};
Rational(int n, int d) {
num = n;
denom = d;
normalize();
}
Rational(int n) {
num = n;
denom = 1;
}
int get_numerator() const {
return num;
}
int get_denominator() const {
return denom;
}
void normalize() {
if ((num > 0 && denom < 0)||(num < 0 && denom < 0)) {
num = -1 * num;
denom = -1 * denom;
}
int gcdcheck = GCD(num,denom);
num = num / gcdcheck;
denom = denom / gcdcheck;
}
int Rational::GCD(int n, int d) {
int temp;
n = abs(n);
d = abs(d);
if (n > d) {
// Do nothing everything is where it should be
}
else {
temp = n;
n = d;
d = temp;
}
int factor = n % d;
while (factor != 0) {
factor = n % d;
d = n;
n = factor;
}
return d;//Return the value to normalize to simplify the fractions to simplist form
}
Rational operator+(Rational b) const {
Rational add;
//Addition of fractions (a*d/b*d + c*b/d*b)
//Numerator = (a*d + c*b)
add.get_numerator = b.get_numerator * denom + b.get_denominator * num;
//Denomenator = (b*d)
add.get_denominator = b.get_denominator * denom;
add.normalize();
return add;
}
Rational operator-(Rational b) const {
Rational sub;
//Same as Addition just a minus sign
//Numerator = (a*d + c*b)
sub.get_numerator = b.get_numerator * denom + b.get_denominator * num;
//Denomenator = (b*d)
sub.get_denominator = b.get_denominator * denom;
sub.normalize();
return sub;
}
Rational operator*(Rational b) const {
//Multiply the numerators and denomenators
Rational multi;
multi.get_numerator = b.get_numerator * num;
multi.get_denominator = b.get_denominator * denom;
multi.normalize();
return multi;
}
Rational operator/(Rational b) const {
//Division of fractions is done by the recipricol of one of the fractions
Rational divi;
divi.get_numerator = b.get_numerator * denom;
divi.get_denominator = b.get_denominator * num;
divi.normalize();
return divi;
}
//To avoid issues with rounding the compare functions will multiply instead to give clean whole numbers
//This will be done by multiplying the denomenators by the opposite numerator
bool operator==(Rational b) const {
return ((b.get_numerator * denom == b.get_denominator * num));
}
bool operator<(Rational b) const {
return ((b.get_numerator * denom > b.get_denominator * num));
}
double toDecimal() const {
double result;
result = static_cast<double> (num)/ static_cast<double> (denom);
return result;
}
private:
int num = 0; // default value is 0
int denom = 1; // default value is 1
};
ostream& operator<<(std::ostream& output, Rational& a) {
if (a.get_denominator == 0) {
output << "Divide by Zero";
}
output << a.get_numerator << '/' << a.get_denominator;
return output;
}
I know its a lot of code and I don't expect someone to go through it all debugging I just thought I would post it all just in case the problem spans farther then where I think the issue is.
I get the same errors for each operator:
1: error C3867: 'Rational::get_denominator': non-standard syntax; use '&' to create a pointer to member
2: '*': error C3867: 'Rational::get_denominator': non-standard syntax; use '&' to create a pointer to member
3: error C3867: 'Rational::get_numerator': non-standard syntax; use '&' to create a pointer to member
I have looked at code from different online sites that have done this problem and tried their methods but it doesn't seem to work. I have added const and & to the parameters in the functions and I still get the same issues. Am I calling a function incorrectly or initializing one wrong?
You have multiple problems in the code. Here is the corrected code.
you were returning a value not a reference.
when you are defining a function inside the class you dont need to specify the full name
the () for function calls were missing
There are some comments on the code at the end.
#include <iostream>
#include <cmath>
using namespace std;
class Rational
{
public:
Rational()
{
num = 0;
denom = 1;
};
Rational(int n, int d)
{`
num = n;
denom = d;
normalize();
}
Rational(int n)
{
num = n;
denom = 1;
}
int& get_numerator()
{
return num;
}
int& get_denominator()
{
return denom;
}
void normalize()
{
if ((num > 0 && denom < 0) || (num < 0 && denom < 0))
{
num = -1 * num;
denom = -1 * denom;
}
int gcdcheck = GCD(num, denom);
num = num / gcdcheck;
denom = denom / gcdcheck;
}
int GCD(int n, int d)
{
int temp;
n = abs(n);
d = abs(d);
if (n > d)
{
// Do nothing everything is where it should be
}
else
{
temp = n;
n = d;
d = temp;
}
int factor = n % d;
while (factor != 0)
{
factor = n % d;
d = n;
n = factor;
}
return d;//Return the value to normalize to simplify the fractions to simplist form
}
Rational operator+(Rational b) const
{
Rational add;
//Addition of fractions (a*d/b*d + c*b/d*b)
//Numerator = (a*d + c*b)
add.get_numerator()= b.get_numerator() * denom + b.get_denominator() * num;
//Denomenator = (b*d)
add.get_denominator() = b.get_denominator() * denom;
add.normalize();
return add;
}
Rational operator-(Rational b) const
{
Rational sub;
//Same as Addition just a minus sign
//Numerator = (a*d + c*b)
sub.get_numerator() = b.get_numerator() * denom + b.get_denominator() * num;
//Denomenator = (b*d)
sub.get_denominator() = b.get_denominator() * denom;
sub.normalize();
return sub;
}
Rational operator*(Rational b) const
{
//Multiply the numerators and denomenators
Rational multi;
multi.get_numerator() = b.get_numerator() * num;
multi.get_denominator() = b.get_denominator() * denom;
multi.normalize();
return multi;
}
Rational operator/(Rational b) const
{
//Division of fractions is done by the recipricol of one of the fractions
Rational divi;
divi.get_numerator() = b.get_numerator() * denom;
divi.get_denominator() = b.get_denominator() * num;
divi.normalize();
return divi;
}
//To avoid issues with rounding the compare functions will multiply instead to give clean whole numbers
//This will be done by multiplying the denomenators by the opposite numerator
bool operator==(Rational b) const
{
return ((b.get_numerator() * denom == b.get_denominator() * num));
}
bool operator<(Rational b) const
{
return ((b.get_numerator() * denom > b.get_denominator() * num));
}
double toDecimal() const
{
double result;
result = static_cast<double> (num) / static_cast<double> (denom);
return result;
}
private:
int num = 0; // default value is 0
int denom = 1; // default value is 1
};
ostream& operator<<(std::ostream& output, Rational& a)
{
if (a.get_denominator() == 0)
{
output << "Divide by Zero";
}
output << a.get_numerator() << '/' << a.get_denominator();
return output;
}
Some comments on the code... Returning a reference, especially to a private member is really bad. I suggest you to create a set function.
so basically keep the get function as before
int get_denominator() const
{
return denom;
}
and create a new function to set value
int set_denominator(int in)
{
denom = in;
}
You try to call the function without the parethesis. It should be get_denominator()
Without the parenthesis you get the pointer to the function instead and try to perform an arythmetic on it - hence the error.

when launching boost::thread the .exe chrashes

This is my function:
void cmdChangeSett(cmdbuf* cmd_buffer, CTimeTag tagger, uint8_t chNum, int mask) {
double* oldChannelvoltage = new double[chNum];
double* newChannelvoltage = new double[chNum];
bool* oldEdge = new bool[chNum];
bool* newEdge = new bool[chNum];
int newmask;
double chDiff;
int edgeDiff;
int i;
while (runAcquisition) {
for (i = 0; i < chNum; i++) {
cmd_getThresh_getEdge(cmd_buffer, i, oldChannelvoltage, oldEdge);
}
Sleep(500);
newmask = 0;
for (i = 0; i < chNum; i++) {
cmd_getThresh_getEdge(cmd_buffer, i, newChannelvoltage, newEdge);
chDiff = oldChannelvoltage[i] - newChannelvoltage[i];
edgeDiff = oldEdge[i] - newEdge[i];
//printf("\nOld: %.2f, New: %.2f -> DIFF = %.2f", oldChannelvoltage[i], newChannelvoltage[i], diff);
if (chDiff != 0) {
WARN(newChannelvoltage[i] > 1.5, newChannelvoltage[i] = 1.5f, "Threshold of %.2fV exceeds channel %i's max. Rounding to %.2fV.", newChannelvoltage[i], i + 1, 1.5);
WARN(newChannelvoltage[i] < -1.5, newChannelvoltage[i] = -1.5f, "Threshold of %.2fV exceeds channel %i's max. Rounding to %.2fV.", newChannelvoltage[i], i + 1, -1.5);
tagger.SetInputThreshold(i + 1, newChannelvoltage[i]);
}
if (edgeDiff) {
if (!newEdge[i]) newmask += 1 << i;
}
}
if (newmask != mask) {
tagger.SetInversionMask(newmask);
mask = newmask;
}
}
delete[] oldChannelvoltage;
delete[] newChannelvoltage;
delete[] oldEdge;
delete[] newEdge;
}
When I launch the thread from the main() it crashes:
int main(int argc, char** argv) {
int mask = 0;
cmdbuf* cmd_buffer;
CTimeTag tagger;
//some code ....
//......
boost::function<void()> cmdChangeSettThread = boost::bind(&cmdChangeSett,cmd_buffer, tagger, 16, mask);
boost::thread th(cmdChangeSettThread);
//some other code ...
return 0;
}
Any idea ??
I thought the problem was caused by the arrays I'm using in the function but I can't figure out how to solve the problem.
Thank you very much!
You need to wait for the thread to finish in main.
If the thread destructor is called and the thread is still running terminate() is called.
th.join(); // should stop the application crashing.
return 0;
}
PS. None of this is good:
double* oldChannelvoltage = new double[chNum];
double* newChannelvoltage = new double[chNum];
bool* oldEdge = new bool[chNum];
bool* newEdge = new bool[chNum];
Use a vector (or an array).
Get a code review: http://codereview.stackexchange.com
Thank you everybody! I found the problem!! I was stupidly passing the object CTimeTag tagger by value, I'm sorry if I wasn't super clear in presenting the problem!
So now the function definition is:
void cmdChangeSett(cmdbuf* cmd_buffer, CTimeTag *tagger, tt_buf* buffer, uint8_t chNum, int mask)
and when I'm calling it with boost::bind I have:
boost::function<void()> cmdChangeSettThread = boost::bind(&cmdChangeSett,cmd_buffer, &tagger, buffer, 16, mask);
Thank you again!

Creating a Linked list with Structs - C++

I was writing a program which could read an input file and store the read data in nodes linked by a "link list". However, I was getting a few errors:
In constructor List::List(), no match for 'operator =' in *((List*)this)->List::list[0] = 0
In constructor Polynomial::Polynomial(): no match for 'operator =' in *((Polynomial*)this)->Polynomial::poly = (operator new(400u), (<statement>), ...)
I have a feeling where I do: I try to access a certain node through an array is where I go wrong, however, I can't figure it out much.
Here is the code:
#include <iostream>
#include <fstream>
using namespace std;
enum result{success, failure};
struct Node
{
double coefficient;
int power;
Node();
Node(double coef, int pwr);
};
struct List
{
Node *list[100];
//Default constructor
List();
};
Node::Node()
{
coefficient = 0;
power = 0;
}
List::List()
{
*list[0] = NULL;
}
Node::Node(double coef, int pwr)
{
coefficient = coef;
power = pwr;
}
class Polynomial
{
public:
Polynomial();
result multiply(Polynomial &p, Polynomial &q);
result add(Polynomial p, Polynomial &q);
void initialize(ifstream &file);
void simplify(Polynomial &var);
void print_poly();
~Polynomial();
private:
List *poly; //Store the pointer links in an array
Node first_node;
int val;
};
Polynomial::Polynomial()
{
*poly = new List();
}
Polynomial::void initialize(ifstream &file)
{
int y[20];
double x[20];
int i = 0, j = 0;
//Read from the file
file >> x[j];
file >> y[j];
first_node(x[j], y[j++]); //Create the first node with coef, and pwr
*poly->list[i] = &first_node; //Link to the fist node
//Creat a linked list
while(y[j] != 0)
{
file >> x[j];
file >> y[j];
*poly->list[++i] = new Node(x[j], y[j++]);
}
val = i+1; //Keeps track of the number of nodes
}
Polynomail::result multiply(Polynomial &p, Polynomial &q)
{
int i, j, k = 0;
for(i = 0; i < p.val; i++)
{
for(j = 0; j < q.val; j++)
{
*poly->list[k] = new Node(0, 0);
*poly->list[k].coefficient = (p.poly->list[i].coefficient)*(q.poly->list[j].coefficient);
*poly->list[k++].power = (p.poly->list[i].power)+(q.poly->list[j].power);
}
}
val = k+1; //Store the nunber of nodes
return success;
}
Polynomial::void simplify(Polynomial &var)
{
int i, j, k = 0;
//Create a copy of the polynomial
for(j = 0; j < var.val; j++)
{
*poly->list[j] = new Node(0, 0);
*poly->list[j].coefficient = var.poly->list[j].coefficient;
*poly->list[j].power = var.poly->list[j].power;
}
//Iterate through the nodes to find entries which have the same power and add them, otherwise do nothing
for(k = 0; k < var.val; k++)
{
for(i = k; i < var.val;)
{
if(*poly->list[k].power == var.poly->list[++i].power)
{
if(*poly->list.power[0] == 0)
{
NULL;
}
else
{
*poly->list[k].coefficient = *poly->list[k].coefficient + var.poly->list[i].ceofficient;
var.poly->list[i] = Node(0, 0);
}
}
}
}
}
Polynomial::void print_pol()
{
int i = 0;
for(i = 0; i < temp.val; i++)
{
cout << "Coefficient: " << temp.poly->list[i].coefficient << ", and " << "Power: " << temp.poly->list[i].power << endl;
}
}
The problem is a wrong dereference. Line 34 should probably be
list[0] = NULL; // remove the *
You try to assign the value NULL to a variable of the type Node, but you probably mean a pointer to Node.
The very same is true in line 63.
In addition, line 66 sould probably b:
void Polynomial::initialize(ifstream &file) // start with return type