IDL equivalents

The interface of vif was designed to facilitate the migration from IDL, an interpreted language that, wile dated, is still commonly used in astronomy. Although IDL as a language suffers from a number of design issues, there is much good in its interface and API that one may wish to emulate in C++. But not all of it.

This page lists common language constructs in IDL and their C++ equivalent with vif. The following table is inspired from the xtensor documentation.

Crucial differences to always keep in mind

  • C++ statements must end with a semicolon ;. Line breaks are treated as white spaces.
  • C++ is a statically typed language: a variable, once created, can never change its type.
  • C++ variables must be declared before being used, and are destroyed automatically once the program exits the scope in which the variables were declared.
  • C++ is a row-major language, IDL is a column-major language: for the same layout in memory (or on the disk), the dimensions of a vector in C++ are reversed compared to IDL. In particular, an image is accessed as img[x,y] in IDL, and img(y,x) in C++.
  • C++ is case-sensitive, so a and A are different objects. Keywords and functions in C++ are always lowercase by convention.

Other notable differences

  • C++ does not have a mechanism for finding where a function’s code is based only on its name. If you put the function in a different file (a “header”), you must #include "..." this header explicitly in all other files that use this function.
  • C++ has no procedures, but functions are allowed to have no return values.
  • vif vectors can be empty, while IDL vectors cannot. It is possible to do operations with an empty vector (which have no cost and do nothing) if all the other vectors involved, if any, are also empty.
  • C++ loops are much faster than in IDL, so there is no need to avoid them except to make the code shorter and more readable.
  • C++ does not support keywords for functions, only normal arguments. A structure with named member values can be used instead.
  • C++ does not have an equivalent for IDL’s common variables (shared between functions), but you can use static to declare variables that survive between different calls to the same function. They just cannot be shared with another function.

Basics

IDL C++ 11 - vif
; a comment // a comment
a = 1
s = 'foo'
int_t a = 1;
std::string s = "foo";
v1 = 1 & v2 = 'bar'
int_t v1 = 1; std::string v2 = "bar";
v = 1 + $
      2 + 3
int_t v = 1 +
      2 + 3;
a = 5
print, 'a=', a
int_t a = 5;
print("a=", a);
print, a, format='(F5.3)' No equivalent with print(), use std::cout or other formatting library.
stop No equivalent. C++ programs either run or crash, but they cannot be stopped and resumed.
r = execute('a = b') No equivalent.
a = 1
delvar, a

; 'a' no longer exist
{
      int_t a = 1;
}
// 'a' no longer exist

Control flow

IDL C++ 11 - vif
if x lt y then begin
      ; ...
endif else begin
      ; ...
endelse
if (x < y) {
      // ...
} else {
      // ...
}
for i=0, n-1 do begin
      ; ...
      break
      ; ...
      continue
      ; ...
endfor
for (uint_t i : range(n)) {
      // ...
      break;
      // ...
      continue;
      // ...
}
array = ['foo','bar','blob']
foreach val, array do begin
      ; ...
endforeach
vec1s array = {"foo","bar","blob"};
for (std::string val : array) {
      // ...
}
while a gt b do begin
      ; ...
endfor
while (a > b) {
      // ...
}
repeat begin
      ; ...
endrep until a gt b
do {
      // ...
} while (a > b);
switch i of
1: print, 'one'
2: print, 'two'
3: print, 'three'
4: begin
      print, 'four'
      break
    end
else: print, 'other'
endswitch

switch (i) {
case 1: print("one");
case 2: print("two");
case 3: print("three");
case 4:
      print("four");
      break;

default: print("other");
}
Note: only works with integers, no strings.
case i of
      ; ...
endcase
No direct equivalent. Use switch() and
be sure to call break; at the end of
each case.

Creating, accessing, modifying vectors

IDL C++ 11 - vif
v = fltarr(10)
v = fltarr(20)
vec1f v(10);
v.resize(20);
v = intarr(5)
d = double(v)
vec1i v(10);
vec1d d = v;
v = intarr(5)
v = double(v)
No equivalent. Types in C++ are static, cannot change int to double.
v = intarr(6)
d = reform(v, 3, 2)
vec1i v(6);
vec2i d = reform(v, 2, 3);
v = intarr(2, 3)
v = reform(v, 3, 2)
vec2i v(3, 2);
v = reform(v, 2, 3);
v = intarr(6)
v = reform(v, 3, 2)
No equivalent. The number of dimensions of a vector is part of its type, and cannot change.
v = [1,2,5,7]
v = [1,2,3]
vec1i v = {1,2,5,7};
v = {1,2,3};
n_elements(v) v.size();
v = dindgen(5) vec1d v = dindgen(5);
v = indgen(2,3)
v[0] = 1
v[0,2] = 2
v[0,*] = [2,5,6]
v[0,*:1] = [5,6]
v[0,1:*] = [5,6]
v[0,1:2] = [5,6]
vec2i v = indgen(3,2);
v[0] = 1;
v(2,0) = 2;
v(_,0) = {2,5,6};
v(_-1,0) = {5,6};
v(1-_,0) = {5,6};
v(1-_-2,0) = {5,6};
v = intarr(5)
w = intarr(5)
id = [1,3,4]
v[id] = 1
v[id] = [-1,0,1]
w[id] = v[id]
vec1i v(5);
vec1i w(5);
vec1u id = {1,3,4};
v[id] = 1;
v[id] = {-1,0,1};
w[id] = v[id];
v = intarr(5)
v[0] = [1,2] (optimized assignment)
vec1i v(5);
v[0-_-1] = {1,2}; (need explicit range)
v = temporary(v) + 1 v = std::move(v) + 1;

Vector operations

IDL C++ 11 - vif
Arithmetic:
x = v + w
x = v - w
x = v * w
x = v / w
x = v ^ w
x = v mod w
x = v mod w

x = v + w;
x = v - w;
x = v * w;
x = v / w;
x = pow(v, w);
x = v % w; (for integers)
x = fmod(v, w); (for floats)
Comparison:
x = v gt w
x = v ge w
x = v lt w
x = v le w
x = v && w
x = v || w
x = ~w
x = v >  w
x = v <  w

x = v >  w;
x = v >= w;
x = v <  w;
x = v <= w;
x = v && w;
x = v || w;
x = !w;
x = max(v, w);
x = min(v, w);
Bitwise:
x = v and w
x = v or  w
x = v xor w
x = not w

x = v & w;
x = v | w;
x = v ^ w;
x = ~w;
Matrix:
x = v # w





matrix::mat<T> w, v;
x = w * v;
or
vec<2,T> w, v;
x = matrix::wrap(w)*matrix::wrap(v);
x = v ## w No direct equivalent. Do the operation explicitly with indices in a loop.

Finding values

IDL C++ 11 - vif
v = [1,2,3,4,5]
id = where(v gt 3, cnt)
if cnt ne 0 then v[id] = 0


vec1f v = {1,2,3,4,5};
vec1u id = where(v > 3);
v[id] = 0;
Note: empty vectors are allowed in vif,
so the check for cnt is not needed.