14

im trying to write a similar version of python's numpy.linspace function.

double linspace(int a, int b, int c){
    double line[c];
    double delta =b-a/(c-1);
    for (int i=0; i<c; ++i){
            line[i]=0 + (i*delta);
    }
    return line;

with a and b being the first and the last component in the array, and c specifying the number of elements in the array. But when i compile this script it returns:

linspace.cpp: In function ‘double linspace(int, int, int)’:
linspace.cpp:11:9: error: cannot convert ‘double*’ to ‘double’ in return
  return line;
         ^

would anyone happen to knw how to solve this problem?

user2804865
  • 976
  • 2
  • 9
  • 15
  • Also, `b-a/(c-1)` (did you mean `(b-a)/(c-1)`?) is integer division. – T.C. Nov 20 '14 at 00:06
  • [This question](https://stackoverflow.com/questions/11169418/numpy-style-arrays-for-c) may be of interest. Summarizes a bunch of libraries that mimic numpy in c++. – topher217 Feb 18 '21 at 05:21

2 Answers2

24

How about something like this:

#include <iostream>
#include <vector>

template<typename T>
std::vector<double> linspace(T start_in, T end_in, int num_in)
{

  std::vector<double> linspaced;

  double start = static_cast<double>(start_in);
  double end = static_cast<double>(end_in);
  double num = static_cast<double>(num_in);

  if (num == 0) { return linspaced; }
  if (num == 1) 
    {
      linspaced.push_back(start);
      return linspaced;
    }

  double delta = (end - start) / (num - 1);

  for(int i=0; i < num-1; ++i)
    {
      linspaced.push_back(start + delta * i);
    }
  linspaced.push_back(end); // I want to ensure that start and end
                            // are exactly the same as the input
  return linspaced;
}

void print_vector(std::vector<double> vec)
{
  std::cout << "size: " << vec.size() << std::endl;
  for (double d : vec)
    std::cout << d << " ";
  std::cout << std::endl;
}

int main()
{
  std::vector<double> vec_1 = linspace(1, 10, 3);
  print_vector(vec_1);

  std::vector<double> vec_2 = linspace(6.0, 23.4, 5);
  print_vector(vec_2);

  std::vector<double> vec_3 = linspace(0.0, 2.0, 1);
  print_vector(vec_3);

  std::vector<double> vec_4 = linspace(0.0, 2.0, 0);
  print_vector(vec_4);


  return 0;
}

C++ result:

size: 3
1 5.5 10 
size: 5
6 10.35 14.7 19.05 23.4 
size: 1
0 
size: 0

Numpy result:

In [14]: np.linspace(1, 10, 3)
Out[14]: array([  1. ,   5.5,  10. ])

In [15]: np.linspace(6, 23.4, 5)
Out[15]: array([  6.  ,  10.35,  14.7 ,  19.05,  23.4 ])

In [16]: np.linspace(0.0, 2.0, 1)
Out[16]: array([ 0.])

In [17]: np.linspace(0.0, 2.0, 0)
Out[17]: array([], dtype=float64)
Akavall
  • 82,592
  • 51
  • 207
  • 251
2

What you are trying to do what won't work. First off you are allocating the memory on the stack WITHIN linspace with

double line[c];

You either new to allocate the memory before the call and pass it in, or allocate it dynamically and return it (and remember to free it later).

To allocate dynamically you can do the following:

double * line = new double[c];

Again, this will need to be freed like so at some point later when you are finished with it, otherwise you will have a memory leak.

delete line[];

Also double line[c]; creates an array of doubles and line points to that. So line is a double *. You specified the return type of the function as double

sedavidw
  • 11,116
  • 13
  • 61
  • 95
  • An example of what? If you change `double line[c];` to 'double * line = new double[c];` and change the return type of the function you are done. Whenever you are done with the data, whatever is returned from this function needs to be deleted. So... `double * lin_ret = linspace(a,b,c);` After you are done with `lin_ret` do `delete lin_ret[];` – sedavidw Nov 19 '14 at 23:04
  • Ha! An *asker* requesting an example! That's rich. – farenorth Nov 19 '14 at 23:22
  • 3
    You really should use a vector for this rather than naked `new`. – T.C. Nov 20 '14 at 00:05