?: beyond the ternary operator (PHP surprise)

Here is a famous ternary operator in C:

condition ? A : B

It can also be conveniently chained:

condition1 ? A : condition2 ? B : condition3 ? C : D

The evaluation of the conditions are in turns: condition1, condition2, condition 3 …

However I had a surprise the other day with PHP:

condition1 ? A : condition2 ? B : condition3 ? C : D

evaluates as:

((condition1 ? A : condition2) ? B : condition3) ? C : D

rather than:

condition1 ? A : (condition2 ? B : (condition3 ? C : D))
Posted in programming | Leave a comment

Populate and serialize text options (Java and C++)

I find it convenient to have a unified text options, similar to those ini/rc files, with serializer/de-serializer for both Java and C++ and here is it.

Sample text file:

testmode=3
block_repeat=100
# floating point
scaling_factor=0.9
# arrays
c=1.0, -2.0, 1.0
b[0]=-1.5, 2.0, -0.5, 0.0
b[1]=0.0, 0.5
b[2]=0.00000000e+00, 6.78046882e-01, -8.91344100e-02
b[3]=0.00000000e+00, 7.75490344e-01, -1.71563059e-01, 2.25807708e-02
# strings
log_file=/tmp/test.log

Java source:

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Options {

  private void init() {
    opt_l = new HashMap<String, Long>();
    opt_f = new HashMap<String, Float>();
    opt_ff = new HashMap<String, Double>();
    opt_s = new HashMap<String, String>();
  }

  public Options() {
    init();
    doublePrecision = false;
  }

  public Options(Boolean dblPrecision) {
    init();
    doublePrecision = dblPrecision;
  }

  public Options(String text) {
    init();
    doublePrecision = false;
    from(text);
  }

  public Options(String text, Boolean dblPrecision) {
    init();
    doublePrecision = dblPrecision;
    from(text);
  }

  private HashMap<String, Long> opt_l;

  private HashMap<String, Float> opt_f;

  private HashMap<String, Double> opt_ff;

  private HashMap<String, String> opt_s;

  private List validKeys_s, validKeys_f, validKeys_l;

  private Boolean doublePrecision;

  /* (non-Javadoc)
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    StringBuilder str = new StringBuilder(512);
    str.append("_double_precision = " + (doublePrecision ? 1 : 0) + "\n");
    str.append("; ======== Integer Options ========\n");
    for (Map.Entry<String, Long> entry : opt_l.entrySet()) {
      str.append(entry.getKey() + " = " + entry.getValue() + "\n");
    }
    str.append("; ======== " + (doublePrecision ? "Double" : "Float") + " Options ========\n");
    for (Map.Entry<String, Float> entry : opt_f.entrySet()) {
      str.append(entry.getKey() + " = " + String.format("%.8e", entry.getValue()) + "\n");
    }
    for (Map.Entry<String, Double> entry : opt_ff.entrySet()) {
      str.append(entry.getKey() + " = " + String.format("%.16e", entry.getValue()) + "\n");
    }
    str.append("; ======== String Options ========\n");
    for (Map.Entry<String, String> entry : opt_s.entrySet()) {
      str.append(entry.getKey() + " = " + entry.getValue() + "\n");
    }

    return str.toString();
  }

  public void from(String text) {
    for (String line : text.split("[\\r\\n]+")) {
      parseLine(line);
    }
  }

  /**
   * Test the regex before using it
   */
  @Deprecated
  public static Boolean isNumber(String str) {
    return str.matches("\\d") && str.matches("^[+-]?\\d*\\.?\\d*([eE]\\d)?\\d*$");
  }

  public static Boolean isInteger(String str) {
    return str.matches("^[+-]?\\d+$");
  }

  public Boolean isDoublePrecision() {
    return doublePrecision;
  }

  public void setDoublePrecision(boolean state) {
    doublePrecision = state;
  }

  public void parseLine(String line) {
    line.trim();
    if (line.startsWith(";") || line.startsWith("#")) {
      return;
    }
    String[] pair = line.split("\\s*=\\s*", 2);
    if (pair.length < 2) {       return;     }     try {       long v = Long.parseLong(pair[1]);       if (pair[0].equals("_double_precison") && v > 0) {
        doublePrecision = true;
      } else {
        opt_l.put(pair[0], v);
      }
    } catch (NumberFormatException e1) {
      try {
        double v = Double.parseDouble(pair[1]);
        if (doublePrecision) {
          opt_ff.put(pair[0], v);
        } else {
          opt_f.put(pair[0], (float) v);
        }
      } catch (NumberFormatException e2) {
        opt_s.put(pair[0], pair[1]);
      }
    }
  }

  public void clear() {
    opt_l.clear();
    opt_f.clear();
    opt_ff.clear();
    opt_s.clear();
  }

  public long getl(String key, long... default_v) {
    long v = default_v.length > 0 ? default_v[0] : 0;
    return opt_l.containsKey(key) ? opt_l.get(key) : v;
  }

  /*
   * Does not return boolean, instead, an interger indicates how many alternative settings are there
   */
  public int countl(String key) {
    return opt_l.containsKey(key) ? 1 : 0;
  }

  public int geti(String key, int... default_v) {
    int v = default_v.length > 0 ? default_v[0] : 0;
    return (int) getl(key, v);
  }

  public int counti(String key) {
    return countl(key);
  }

  public double getff(String key, double... default_v) {
    double v = default_v.length > 0 ? default_v[0] : 0;
    return opt_ff.containsKey(key) ? opt_ff.get(key) : opt_f.containsKey(key) ? opt_f.get(key)
        : opt_l.containsKey(key) ? opt_l.get(key) : v;
  }

  public int countff(String key) {
    return (opt_ff.containsKey(key) ? 1 : 0) + (opt_f.containsKey(key) ? 1 : 0) + (opt_l.containsKey(key) ? 1 : 0);
  }

  public float getf(String key, float... default_v) {
    float v = default_v.length > 0 ? default_v[0] : 0;
    return opt_f.containsKey(key) ? opt_f.get(key) : opt_ff.containsKey(key) ? opt_ff.get(key).floatValue() : opt_l
        .containsKey(key) ? opt_l.get(key) : v;
  }

  public int countf(String key) {
    return countff(key);
  }

  public String gets(String key, String... default_v) {
    String v = default_v.length > 0 ? default_v[0] : "";
    return opt_s.containsKey(key) ? opt_s.get(key) : v;
  }

  public int counts(String key) {
    return opt_s.containsKey(key) ? 1 : 0;
  }

  public boolean containsLong(String key) {
    return countl(key) > 0;
  }

  public boolean containsInt(String key) {
    return counti(key) > 0;
  }

  public boolean containsDouble(String key) {
    return countff(key) > 0;
  }

  public boolean containsFloat(String key) {
    return countf(key) > 0;
  }

  public boolean containsString(String key) {
    return counts(key) > 0;
  }

  public void set(String key, long v) {
    opt_l.put(key, v);
  }

  public void set(String key, int v) {
    opt_l.put(key, (long) v);
  }

  public void set(String key, double v) {
    if (doublePrecision) {
      opt_ff.put(key, v);
    } else {
      opt_f.put(key, (float) v);
    }
  }

  public void set(String key, float v) {
    if (doublePrecision) {
      opt_ff.put(key, (double) v);
    } else {
      opt_f.put(key, v);
    }
  }

  public void set(String key, String v) {
    opt_s.put(key, v);
  }

  public static void main(String[] args) {
    Options opt = new Options("int1=1\nfloat2= 3.0 \nfloat3= .3e-5 \nstring_test = TEST STRING");
    System.out.println(opt);
    String text = opt.toString();
    opt = new Options(text, true);
    System.out.println(opt);
  }

  public static String floats2str(float[] v) {
    String val = String.format("%.8e", v[0]);
    for (int i = 1; i < v.length; i++) {
      val += String.format(", %.8e", v[i]);
    }
    return val;
  }

  public static String doubles2str(double[] v) {
    String val = String.format("%.16e", v[0]);
    for (int i = 1; i < v.length; i++) {
      val += String.format(", %.16e", v[i]);
    }
    return val;
  }

  /**
   * This method sets a string entry of the arrays with sufficient precisions
   * for simplicity, no { } to enclose it (no plan to support 2D array)
   */
  public void set(String key, float[] v) {
    set(key, floats2str(v));
  }

  public void set(String key, double[] v) {
    set(key, doubles2str(v));
  }

  /*
   * This method will fail if cannot parse properly
   */
  public static float[] str2floats(String str) {
    String[] strs = str.split(",\\s*");
    float[] floats = new float[strs.length];

    for (int i = 0; i < strs.length; i++) {
      floats[i] = Float.parseFloat(strs[i]);
    }
    return floats;
  }

  /*
   * This method will fail if cannot parse properly
   */
  public static double[] str2doubles(String str) {
    String[] strs = str.split(",\\s*");
    double[] doubles = new double[strs.length];

    for (int i = 0; i < strs.length; i++) {       doubles[i] = Double.parseDouble(strs[i]);     }     return doubles;   }   public float[] getFloats(String key, float[]... default_v) {     float[] v = default_v.length > 0 ? default_v[0] : null;
    return opt_s.containsKey(key) ? str2floats(opt_s.get(key)) : v;
  }

  public double[] getDoubles(String key, double[]... default_v) {
    double[] v = default_v.length > 0 ? default_v[0] : null;
    return opt_s.containsKey(key) ? str2doubles(opt_s.get(key)) : v;
  }

  public void print_validKeys() {
    System.out.printf("Valid int keys: %s\n", validKeys_l);
    System.out.printf("Valid float keys: %s\n", validKeys_f);
    System.out.printf("Valid string keys: %s\n", validKeys_s);
  }

  private boolean validate_keys(List validKeys, Set keys, String description) {
    Iterator it = keys.iterator();
    boolean valid = true;
    while (it.hasNext()) {
      String key = it.next();
      if (!key.startsWith("_") && !validKeys.contains(key)) { // keys start with _ are exempted from validation
        System.out.printf("ERROR: Invalid %s key for text options: %s\n", description, key);
        valid = false;
      }
    }

    return valid;
  }

  public boolean validate_keys() {
    boolean valid = true;
    valid &= validate_keys(validKeys_l, opt_l.keySet(), "int"); // a = a && b will short circuit, which we do not want
    valid &= validate_keys(validKeys_f, opt_f.keySet(), "float");
    valid &= validate_keys(validKeys_f, opt_ff.keySet(), "float");
    valid &= validate_keys(validKeys_s, opt_s.keySet(), "string");
    if (!valid) {
      print_validKeys();
    }
    return valid;
  }

  public void setValidStringKeys(List keys) {
    validKeys_s = keys;
  }

  public void setValidFloatKeys(List keys) {
    validKeys_f = keys;
  }

  public void setValidIntKeys(List keys) {
    validKeys_l = keys;
  }
}

C++ source:

Options.h:

#ifndef OPTIONS_H_
#define OPTIONS_H_

#include <map>
using std::string;
using std::map;
typedef map<string, int> map_i;
typedef map<string, long> map_l;
typedef map<string, float> map_f;
typedef map<string, double> map_ff;
typedef map<string, string> map_s;

class COptions {
public:
    map_l opt_l;
    map_f opt_f;
    map_ff opt_ff;
    map_s opt_s;
private:
    int doublePrecision;
public:
    COptions();
    COptions(const char* text);
    COptions(string str);
    virtual ~COptions();

    COptions& operator<<(const char* text);
    COptions& operator<<(const string& str);
    COptions& operator<<(std::istream& is);     COptions& operator>>(std::ostream& os);
    friend std::istream& operator>>(std::istream& is, COptions&);
    friend std::ostream& operator<<(std::ostream& os, const COptions&);

    void clear();
    void reset();
    virtual void init_defs(); // for overriding ...
    string to_string();
//    const char * c_str(); // NO NO!!!

    int isDoublePrecision();
    int geti(const char* key, int def = 0);
    long getl(const char* key, long def = 0L);
    float getf(const char* key, float def = 0.0f);
    double getff(const char* key, double def = 0.0);
    string gets(const char* key, string def = "");

    vector getFloats(const char* key);
    vector getFloats(const char* key, vector& def);
    vector getDoubles(const char* key);
    vector getDoubles(const char* key, vector& def);

    int counti(const char* key);
    int countl(const char* key);
    int countf(const char* key);
    int countff(const char* key);
    int counts(const char* key);

    void set(const char* key, int val);
    void set(const char* key, long val);
    void set(const char* key, float val);
    void set(const char* key, double val);
    void set(const char* key, vector vec);
    void set(const char* key, vector vec);
    void set(const char* key, string val);

    void parse_line(string& line);
    void chop_space(string& str);

    static vector str2floats(string& str);
    static vector str2doubles(string& str);
    static string floats2str(vector& vec);
    static string doubles2str(vector& vec);
    static int test();
};

#endif /* OPTIONS_H_ */

Options.cpp:

#include "Options.h"
#include <sstream>
#include <iostream>
#include <iterator>
#include <iomanip>
#include <limits>

COptions::COptions(const char* text) {
  init_defs();
  *this << text;
}

COptions::COptions(string str) {
  init_defs();
  *this << str;
}

COptions::COptions() {
  init_defs();
}

COptions::~COptions() {

}

void COptions::clear() {
  opt_l.clear();
  opt_f.clear();
  opt_ff.clear();
  opt_s.clear();
}

void COptions::reset() {
  clear();
  init_defs();
}

void COptions::init_defs() {
  doublePrecision = 0;
}

COptions& COptions::operator <<(const char* text) {
  if (!text) return *this;

  std::stringstream ss(text);
  return (*this << ss);
}

COptions& COptions::operator <<(const string& str) {
  if (str.empty()) return *this;

  std::stringstream ss(str);
  return (*this << ss);
}

COptions& COptions::operator <<(std::istream& is) {   string line;   while (std::getline(is, line))     parse_line(line);   return *this; } COptions& COptions::operator >>(std::ostream& os) {
  os << *this;   return *this; } std::istream& operator >>(std::istream& is, COptions& me) {
  me << is;
  return is;
}

std::ostream& operator <<(std::ostream& os, const COptions& me) {
  os << "_double_precision = " << (me.doublePrecision ? 1 : 0) << std::endl;
  os << "; =======Integer options=======" << std::endl;
  for (map_l::const_iterator iter = me.opt_l.begin(); iter != me.opt_l.end(); iter++)
    os << iter->first << " = " << iter->second << std::endl;

  os << "; =======" << (me.doublePrecision ? "Double" : "Float") << " options=======" << std::endl;   for (map_f::const_iterator iter = me.opt_f.begin(); iter != me.opt_f.end(); iter++) {     float f = iter->second;
    //if ((float) ((int) nearbyintf(f)) == f) os << iter->first << " = " << iter->second << ".0" << std::endl;
    //else os << iter->first << " = " << iter->second << std::endl;
    os << iter->first << " = " << std::scientific
        << std::setprecision(std::numeric_limits::digits10 + 1) // 7+1, same as %.8e, totally 9 digits
        << f << std::endl;   }   for (map_ff::const_iterator iter = me.opt_ff.begin(); iter != me.opt_ff.end(); iter++) {     double f = iter->second;
    //if ((double) ((int) nearbyint(f)) == f) os << iter->first << " = " << iter->second << ".0" << std::endl;
    //else os << iter->first << " = " << iter->second << std::endl;
    os << iter->first << " = " << std::scientific
        << std::setprecision(std::numeric_limits::digits10 + 1) // 15+1, same as %.16e, totally 17 digits
        << f << std::endl;
  }

  os << "; =======String options=======" << std::endl;
  for (map_s::const_iterator iter = me.opt_s.begin(); iter != me.opt_s.end(); iter++)
    os << iter->first << " = " << iter->second << std::endl;
  return os;
}

void COptions::parse_line(string& line) {
  if (line[0] == ';' || line[0] == '#') return; // comment line
  size_t pos = line.find('=');
  if (pos == string::npos) return;
  string key = line.substr(0, pos);
  string val = line.substr(pos + 1);
  chop_space(key);
  chop_space(val);
  if (key.empty() || val.empty()) return;
  // std::cout << "key = " << key << ", val = " << val << std::endl;   if (val.find_first_not_of("+-0123456789") == string::npos) {     if (key.compare("_double_precision") == 0) doublePrecision = atol(val.c_str());     else opt_l[key] = atol(val.c_str()); // integer   }   // floating point, not fool-proof but sufficient ...   else if ((val.find_first_of("0123456789") != string::npos)       && (val.find_first_not_of("+-.0123456789eE") == string::npos)) {     if (doublePrecision) opt_ff[key] = atof(val.c_str());     else opt_f[key] = atof(val.c_str());   } else opt_s[key] = val; // string } void COptions::chop_space(string& str) {   size_t pos;   if ((pos = str.find_first_not_of(" \t\n\r")) > 0) str = str.substr(pos); // remove leading spaces
  if ((pos = str.find_last_not_of(" \t\n\r")) < str.size() - 1) str = str.substr(0, pos + 1); // remove trailing spaces
}

string COptions::to_string() {
  std::stringstream ss(std::stringstream::out);

  ss << *this;

  return ss.str();
}

/* should not do like this, to_string() will be free'ed and c_str() will be meaningless
 const char* COptions::c_str() {
 return to_string().c_str();
 }
 */

int COptions::geti(const char* key, int def) {
  return opt_l.count(key) ? opt_l[key] : def;
}

long COptions::getl(const char* key, long def) {
  return opt_l.count(key) ? opt_l[key] : def;
}

float COptions::getf(const char* key, float def) {
  return opt_f.count(key) ? opt_f[key] : opt_ff.count(key) ? opt_ff[key] : opt_l.count(key) ? opt_l[key] : def;
}

double COptions::getff(const char* key, double def) {
  return opt_ff.count(key) ? opt_ff[key] : opt_f.count(key) ? opt_f[key] : opt_l.count(key) ? opt_l[key] : def;
}

string COptions::gets(const char* key, string def) {
  return opt_s.count(key) ? opt_s[key] : def;
}

void COptions::set(const char* key, int val) {
  opt_l[key] = val;
}

void COptions::set(const char* key, long val) {
  opt_l[key] = val;
}

void COptions::set(const char* key, float val) {
  opt_f[key] = val;
}

void COptions::set(const char* key, double val) {
  opt_ff[key] = val;
}

void COptions::set(const char* key, string val) {
  opt_s[key] = val;
}

int COptions::test() {
  const char text[] = "_double_precision = 1\nint1= 2\n float2=0.0 \n string3 = TEST STRING  \n float4 = 0.01";
  COptions opt;
  opt.clear();
  opt << text;
  std::cout << opt << std::endl;

  string str = opt.to_string();
  opt.reset();
  opt << str;
  std::cout << opt << std::endl;

  COptions opt2(text);
  std::cout << opt2 << std::endl;

  return 0;
}

int COptions::isDoublePrecision() {
  return doublePrecision;
}

vector COptions::getFloats(const char* key) {
  if (opt_s.count(key)) return str2floats(opt_s[key]);
  vector v;
  if (countf(key)) v.push_back(getf(key)); // handles size=1
  return v;
}

vector COptions::getFloats(const char* key, vector& def) {
  if (opt_s.count(key)) return str2floats(opt_s[key]);
  if (countf(key)) { // handles size=1
    vector v;
    v.push_back(getf(key));
    return v;
  }
  return def;
}

vector COptions::getDoubles(const char* key) {
  if (opt_s.count(key)) return str2doubles(opt_s[key]);
  vector v;
  if (countff(key)) v.push_back(getff(key)); // handles size=1
  return v;
}

vector COptions::getDoubles(const char* key, vector& def) {
  if (opt_s.count(key)) return str2doubles(opt_s[key]);
  if (countff(key)) { // handles size=1
    vector v;
    v.push_back(getff(key));
    return v;
  }
  return def;
}

int COptions::counti(const char* key) {
  return opt_l.count(key);
}

int COptions::countl(const char* key) {
  return opt_l.count(key);
}

int COptions::countf(const char* key) {
  return opt_f.count(key) + opt_ff.count(key) + opt_l.count(key);
}

int COptions::countff(const char* key) {
  return opt_ff.count(key) + opt_f.count(key) + opt_l.count(key);
}

int COptions::counts(const char* key) {
  return opt_s.count(key);
}

vector COptions::str2floats(string& str) {
  std::stringstream iss(str);
  vector v;

  float val;
  char c;
  while (iss >> val) {
    v.push_back(val);
    while ((c = iss.peek()) == ',' || c == ' ')
      iss.get();
  }
  return v;
}

vector COptions::str2doubles(string& str) {
  std::stringstream iss(str);
  vector v;

  double val;
  char c;
  while (iss >> val) {
    v.push_back(val);
    while ((c = iss.peek()) == ',' || c == ' ')
      iss.get();
  }
  return v;
}

string COptions::floats2str(vector& vec) {
  std::ostringstream ss;
  ss << std::scientific << std::setprecision(std::numeric_limits::digits10 + 1) // 7+1, same as %.8e, totally 9 digits
      << vec[0];
  for (size_t i = 1; i < vec.size(); i++) {
    ss << ", " << std::scientific << std::setprecision(std::numeric_limits::digits10 + 1) // 7+1, same as %.8e, totally 9 digits
        << vec[i];
  }
  return ss.str();
}

string COptions::doubles2str(vector& vec) {
  std::ostringstream ss;
  ss << std::scientific << std::setprecision(std::numeric_limits::digits10 + 1) // 15+1, same as %.16e, totally 17 digits
      << vec[0];
  for (size_t i = 1; i < vec.size(); i++) {
    ss << ", " << std::scientific << std::setprecision(std::numeric_limits::digits10 + 1) // 15+1, same as %.16e, totally 17 digits
        << vec[i];
  }
  return ss.str();
}

void COptions::set(const char* key, vector vec) {
  set(key, floats2str(vec));
}

void COptions::set(const char* key, vector vec) {
  set(key, doubles2str(vec));
}

Posted in programming | 2 Comments

Lapack Java SGBTRF and SGBTRS

A sample code in Java, as a memo of the correct indexing (row/col):

import org.netlib.lapack.Sgbtrf;
import org.netlib.lapack.Sgbtrs;
  /*
  Purpose:
    We want to use the LAPACK routines SGBTRF and SGBTRS to solve a banded 
    linear system of the form A*x=b.  Our 4x4 version of this problem is:

      2.0 -1.0  0.0  0.0   x(0)      0.0
     -1.0  2.0 -1.0  0.0 * x(1)  =   0.0
      0.0 -1.0  2.0 -1.0   x(2)      0.0
      0.0  0.0 -1.0  2.0   x(3)      5.0

    The solution is x = ( 1, 2, 3, 4 ).
  */
  public static void main(String[] args) {
    int n = 4;
    int m = 2;
    int k = 1; // kl = ku
    float[] AB = { 0, 0, 2, -1, //
        0, -1, 2, -1,//
        0, -1, 2, -1, //
        0, -1, 2, 0 }; // new float[(3 * k + 1)*n];
    float[] B = { 0, 0, 0, 5, 0, 0, 0, 5 }; //new float[n*m];
    int[] IPIV = new int[n];
    intW info = new intW(0);

    Sgbtrf.sgbtrf(n, n, k, k, AB, 0, 3 * k + 1, IPIV, 0, info);
    System.out.println("Info = " + info.val);

    Sgbtrs.sgbtrs("N", n, k, k, m, AB, 0, 3 * k + 1, IPIV, 0, B, 0, n, info);
    System.out.println("Info = " + info.val);
    System.out.println("Solution: " + Arrays.toString(B));

    n = 10;
    m = 2;
    k = 3;
    AB = new float[(3 * k + 1) * n];
    B = new float[n * m];
    IPIV = new int[n];
    for (int i = 0; i < n; i++) {
      for (int j = Math.max(0, i - k); j <= i; j++) {
        if (i == j) {
          AB[k * 2 + i - j + j * (3 * k + 1)] = 2;
        } else if (i == j + 1 || i == j - 1) {
          AB[k * 2 + i - j + j * (3 * k + 1)] = -1;
        }
      }
    }
    for (int i = 0; i < n; i++) {
      for (int j = Math.max(0, i - k); j < i; j++) {
        AB[k * 2 + j - i + i * (3 * k + 1)] = AB[k * 2 + i - j + j * (3 * k + 1)];
      }
    }
    System.out.println("AB: " + Arrays.toString(AB));
    for (int i = 0; i < m; i++) {
      B[(i + 1) * n - 1] = n + 1;
    }

    Sgbtrf.sgbtrf(n, n, k, k, AB, 0, 3 * k + 1, IPIV, 0, info);
    System.out.println("Info = " + info.val);

    Sgbtrs.sgbtrs("N", n, k, k, m, AB, 0, 3 * k + 1, IPIV, 0, B, 0, n, info);
    System.out.println("Info = " + info.val);
    System.out.println("Solution: " + Arrays.toString(B));
  }
Posted in programming | Leave a comment

Overloading open() and fopen()

One can overload fopen() and open() for debugging purpose, the example below traces each file opening operation:

#include 
#include 
static FILE * (*next_fopen)(const char *path, const char *mode);

FILE * fopen(const char *path, const char *mode) {
    char *msg;

    if (next_fopen == NULL) {
        next_fopen = dlsym(RTLD_NEXT, "fopen");
        if ((msg = dlerror()) != NULL)
            printf("**fopen dlopen failed : %s\n", msg);
    }

    printf("*fopen : %s\n", path);
    return next_fopen(path, mode);
}

static int (*next_open)(const char *path, int oflag, ...);

int open(const char *path, int oflag, ...) {
    char *msg;

    if (next_open == NULL) {
        next_open = dlsym(RTLD_NEXT, "open");
        if ((msg = dlerror()) != NULL)
            printf("**open dlopen failed : %s\n", msg);
    }

    printf("*open : %s\n", path);
    va_list args;
    va_start(args, path);
    mode_t mode = va_arg(args, mode_t);
    int fd = next_open(path, oflag, mode); // handle vararg
    va_end(args);
    return fd;
}
Posted in programming | Leave a comment

debug MPI programs with many slaves

Although ddt is handy, in some cases one might want to do it the old fashioned way (e.g., debugging many nodes that exceeds the license limit, or, you do not have ddt).

Instead opening 30 terminals and attach gdb to the process manually, the procedure below turns out to be useful:

 1)  I have a small script called gdbwait in my path, this script can be used manually to wait for a process to be launched, or, used automatically in steps 2) and 3). I am not sure if I need to use –o or –n option for “pgrep” to catch the right pid, but for single process on each node, it does not matter.

#!/bin/sh
progstr=$1
progpid=`pgrep -o $progstr`
while [ "$progpid" = "" ]; do
progpid=`pgrep -o $progstr`
done
gdb -ex continue -p $progpid

2) For example, we have a program called testme to be debugged, edit a script file with these lines below. It should prepare gdb to wait remotely w/o occupying your workspace/terminals.

rsh slave002 screen -d -m gdbwait testme
rsh slave003 screen -d -m gdbwait testme
rsh slave004 screen -d -m gdbwait testme
rsh slave005 screen -d -m gdbwait testme

3) Wait a while and launch the MPI program … To exam the gdb on slave002, use:

ssh -t slave002 screen -r
[NOTE: to detach, hit these two keystrokes in serial: Ctrl-A, d] 
Google “gnu screen” for the usage of the screen utility.

Posted in programming | Leave a comment

fgsl: single precision float version of gsl

Many of GSL (GNU Scientific Library)’s routines are implemented in double only.  When one needs the additional speed and storage advantage, there wasn’t a quick way to go to float.  Here is a quick hack:

  1. cd gsl-1.15,  edit configure.ac, change
    AC_INIT([gsl],[1.15])
    to
    AC_INIT([fgsl],[1.15])
    Optionally, add an optimization line to make it look like this:
    AC_LANG(C)
    AC_PROG_CC
    AC_PROG_CPP
    CFLAGS="-O3 -mtune=native"
  2. Then, run
    autoconf
    ./configure

    (or, to install to non-default location, ./configure --prefix=/home/me/local)
  3. Now run this cmd to do search and replace
    find . -type f -print0 | xargs -0 perl -pi -e 's/long double/LONG-DOUBLE/g;s/_double/_DOUbLE/g;s/double/float/g;s/_DOUbLE/_double/g;s/LONG-DOUBLE/long double/g;s/libgsl/libfgsl/g;s|<gsl/|<fgsl/|g'
  4. Now you can make and install as normal
    make
    make install

To use it, instead of
#include <gsl/blah.h> 
use:
#include <fgsl/blah.h>

When linking, instead of link with:
-lgsl
or
libgsl.a
use:
-lfgsl
or
libfgsl.a

Posted in programming | Tagged , , | 1 Comment

gcc build error: undefined _Unwind_Ptr

I have tried on build both gcc-4.6.2 and gcc-4.6.1 and failed.  Here is the error:

In file included from ../../.././libgcc/../gcc/unwind-dw2.c:35:0:
../../.././libgcc/../gcc/unwind-pe.h:101:1: error: unknown type name '_Unwind_Ptr'

Solution: rename the first unwind.h to another name and there should be another unwind.h which is good for building gcc.  The cause is the installation of libunwind which is claimed to be cleaner than gcc’s unwind but defined different/less prototypes.

Posted in Info Tech, programming | 1 Comment

Passing class member function as argument

Here is one example:
Declaration:
class CDifferentialFFT : public CDifferential {
  ...
  double benchmark(void (CDifferential::*) (float*, float*, int), float* p, float* pz);
  ...
}

Implementation:
double CDifferentialFFT::benchmark(void (CDifferential::*func) (float*, float*, int), float* p, float* pz) {
  ...
  for (int i = 0; i < nloop; i++) (fft->*func)(p, pz, 1);
  ...
}

Example:
if (fftw->benchmark(&CDifferential::partial_x, p, pz) < fftv->benchmark(&CDifferential::partial_x, p, pz)) diffx = fftw;
else diffx = fftv;
if (fftw->benchmark(&CDifferential::partial_y, p, pz) < fftv->benchmark(&CDifferential::partial_y, p, pz)) diffy = fftw;
else diffy = fftv;
if (fftw->benchmark(&CDifferential::partial_z, p, pz) < fftv->benchmark(&CDifferential::partial_z, p, pz)) diffz = fftw;
else diffz = fftv;

Posted in programming | Tagged , | Leave a comment

calloc for C++?

It’s recommended to use: double * data = new double[mysize]; in C++ rather than the C-way: double * data = (double *)malloc(sizeof(double)*mysize);

How about the one corresponds to calloc( ) ? Short memo here:
double * data = new double[mysize]();

Search the internet for more details if you are interested …

Posted in programming | Tagged | Leave a comment

Install Stereo for 2007 Dodge Grand Caravan

Recently I installed a new stereo for my 2007 Dodge Grand Caravan (the OEM one did not have MP3 capability and could not read from USB) and would like to document the steps for sharing. (Standard no-warranty disclaimer applies here — the materials here are meant to be helpful, USE AT YOUR OWN RISK.)

First, I bought a standard single-DIN sized after-market stereo.  Three adapters are needed to install this onto my Grand Caravan: 1) Metra 99-6503 Dash Kit; 2) Metra 40-CR10 Antenna Adapter Cable; 3) Metra 70-6502 Radio Wiring Harness.  The 3rd one is a bit tricky because model Metra 70-6522 Radio Wiring Harness for Chrysler 2007 is for Grand Caravan 2008 and later — I bought it then found it was wrong and called Metra to get the correct item number.

Preparation: Sold the item 3), the wiring harness to the one comes with the after-market stereo unit. After soldering, tape and insulate the exposed wires. (One could use wire nuts/end caps for connection instead of soldering and tapering.) The colors are quite straightforward to follow (read the label, read the small letters on the wires or read the instruction that comes with the wiring harness).

Preparation 0a: sold wiring harness

Preparation 0b: insulate wiring harness

Step 1 (optional): Remove the cup holder. Pull the cup holder to expose the tab (I circled it in red in the image below). Press the tab and you can take the cup holder out.

step 1-remove cup holder

Step 2: Ply the plastic cover to expose the screws. (As you can see, I have not done the optional Step 1 yet in the photo.)

step2a-ply plastic bar

 

step2b-plastic bar removed

Step 3: Remove the inner two screws. — After the plastic cover bar removed, you can see 4 screws as shown in the photo below.

step 3-remove two screws

Step 4: Ply the main cover. From the bottom, ply it to make it loose, then finally remove the whole panel. The design is not bad, so do not be too worried about breaking the hinges.

step 4-ply main cover

Step 5: Unscrew the stereo unit. — After the main panel removed, the four screws that secure the stereo unit are exposed. Mine only had 2 screws from the factory. The one shown below is indeed my new stereo with the Dash Kit. Inside the red rectangle is my single-DIN sized stereo.

step 5-remove stereo

Step 6: Unhook the original wires (it’s a plug) and the antenna (you need to pull really hard). Then hook the wire harness and the antenna adapter (marked in red frames).

Finally, you can put everything back and enjoy!

To stop spammers, I disabled the comments. If you want to thank me, either drop me an email, or better, post on where did you buy the parts and help more people.

Posted in car | 8 Comments