Index: /trunk/Ohana/src/libohana/Makefile
===================================================================
--- /trunk/Ohana/src/libohana/Makefile	(revision 39039)
+++ /trunk/Ohana/src/libohana/Makefile	(revision 39040)
@@ -45,5 +45,5 @@
 $(SRC)/Fread.$(ARCH).o		 \
 $(SRC)/IOBufferOps.$(ARCH).o	 \
-$(SRC)/memstr.$(ARCH).o	 \
+$(SRC)/memstr.$(ARCH).o	 	 \
 $(SRC)/rconnect.$(ARCH).o	 \
 $(SRC)/CommOps.$(ARCH).o	 \
@@ -51,4 +51,5 @@
 $(SRC)/errors.$(ARCH).o	 \
 $(SRC)/gprint.$(ARCH).o	 \
+$(SRC)/print_floats.$(ARCH).o	 \
 $(SRC)/version.$(ARCH).o
 
@@ -64,5 +65,7 @@
 $(DESTLIB)/libohana.$(DLLTYPE): $(LIB)/libohana.$(ARCH).$(DLLTYPE)
 
-TESTPROG = memtest typetest string 
+TESTPROG = print_floats
+# TESTPROG = memtest typetest string 
+
 $(TESTPROG) : % : $(TESTBIN)/% $(OBJS)
 test: $(TESTPROG)
Index: /trunk/Ohana/src/libohana/include/ohana.h
===================================================================
--- /trunk/Ohana/src/libohana/include/ohana.h	(revision 39039)
+++ /trunk/Ohana/src/libohana/include/ohana.h	(revision 39040)
@@ -483,3 +483,6 @@
 int ohana_bisection_double (double *values, int Nvalues, double threshold);
 
-# endif
+int sprintf_float (char *output, float value);
+int sprintf_double (char *output, double value);
+
+# endif
Index: /trunk/Ohana/src/libohana/src/print_floats.c
===================================================================
--- /trunk/Ohana/src/libohana/src/print_floats.c	(revision 39040)
+++ /trunk/Ohana/src/libohana/src/print_floats.c	(revision 39040)
@@ -0,0 +1,157 @@
+# include <ohana.h>
+
+# define NSIGFIG_FLT  7
+# define NEXPFIG_FLT  2
+
+// returns the number of bytes written EXCLUDING the ending NULL char
+int sprintf_float (char *output, float value) {
+
+  // I want a fast way to print a float in %e format.  Simplifying assumptions: print a
+  // single float to an existing char buffer using a fixed format: +F.ffffffe+NN 
+  // NSIGFIG_FLT = number of digits after decimal point
+
+  // returns: number of chars actually written
+
+  if (value == 0.0) {
+    strcpy (output, "+0.0000000+e00");  // NOTE: hard-wired
+    return 14;
+  }						
+
+  int isPositiveValue = (value > 0.0);
+
+  double pvalue = fabs(value);
+
+  int isPositiveExp = (pvalue >= 1.0);
+
+  // get the exponent
+  double Exponent = log10(pvalue);
+
+  // get the integer component of the exponent
+  int iExponent = floor(Exponent);
+
+  // re-raise to the integer power to grab the Mantissa
+  double power = pow (10.0, (double) iExponent);
+
+  double Mantissa = pvalue / power;
+
+  // multiplier here must be 10^(NSIGFIG_FLT + 1)
+  long long int iMantissa = Mantissa * 100000000;  // NOTE: hard-wired
+  
+  // example, NSIGFIG_FLT = 6
+  // +1.234567e+01 -> 1234567
+  // 0123456789012 == 6543210
+  // 876543210
+
+  // write the leading sign
+  output[0] = isPositiveValue ? '+' : '-';
+
+  // we need to know the NSIGFIG_FLT + 1 digit to know if we should round up or down
+  int roundUp = (iMantissa % 10 > 4);
+  // fprintf (stderr, "%f : %d : %d\n", value, iMantissa, roundUp);
+
+  // now drop iMantissa to the correct number of digits
+  iMantissa = iMantissa / 10;
+  if (roundUp) iMantissa ++;
+
+  // now write out the Mantissa backwards as an integer, but include a decimal point
+  int i;
+  for (i = 0; i < NSIGFIG_FLT + 2; i++) {
+    if (i == NSIGFIG_FLT) {
+      output[NSIGFIG_FLT + 2 - i] = '.';
+      continue;
+    }
+    output[NSIGFIG_FLT + 2 - i] = '0' + iMantissa % 10;
+    iMantissa = iMantissa / 10;
+  }
+    
+  output[NSIGFIG_FLT + 3] = 'e';
+  output[NSIGFIG_FLT + 4] = isPositiveExp ? '+' : '-';
+
+  iExponent = abs(iExponent);
+
+  for (i = 0; i < NEXPFIG_FLT; i++) {
+    output[NSIGFIG_FLT + 4 + NEXPFIG_FLT - i] = '0' + iExponent % 10;
+    iExponent = iExponent / 10;
+  }
+  output[NSIGFIG_FLT + NEXPFIG_FLT + 5] = 0;
+  
+  return NSIGFIG_FLT + NEXPFIG_FLT + 5;
+}
+
+# define NSIGFIG_DBL 14
+# define NEXPFIG_DBL  2
+
+// returns the number of bytes written EXCLUDING the ending NULL char
+int sprintf_double (char *output, double value) {
+
+  // I want a fast way to print a float in %e format.  Simplifying assumptions: print a
+  // single float to an existing char buffer using a fixed format: +F.ffffffe+NN 
+  // NSIGFIG_DBL = number of digits after decimal point
+
+  // returns: number of chars actually written
+
+  if (value == 0.0) {
+    strcpy (output, "+0.00000000000000+e000");  // NOTE: hard-wired
+    return 22;
+  }						
+
+  int isPositiveValue = (value > 0.0);
+
+  double pvalue = fabs(value);
+
+  int isPositiveExp = (pvalue >= 1.0);
+
+  // get the exponent
+  double Exponent = log10(pvalue);
+
+  // get the integer component of the exponent
+  int iExponent = floor(Exponent);
+
+  // re-raise to the integer power to grab the Mantissa
+  double power = pow (10.0, (double) iExponent);
+
+  double Mantissa = pvalue / power;
+
+  // multiplier here must be 10^(NSIGFIG_DBL + 1)
+  long long int iMantissa = Mantissa * 1000000000000000;  // NOTE: hard-wired
+  
+  // example, NSIGFIG_DBL = 6
+  // +1.234567e+01 -> 1234567
+  // 0123456789012 == 6543210
+  // 876543210
+
+  // write the leading sign
+  output[0] = isPositiveValue ? '+' : '-';
+
+  // we need to know the NSIGFIG_DBL + 1 digit to know if we should round up or down
+  int roundUp = (iMantissa % 10 > 4);
+  // fprintf (stderr, "%f : %d : %d\n", value, iMantissa, roundUp);
+
+  // now drop iMantissa to the correct number of digits
+  iMantissa = iMantissa / 10;
+  if (roundUp) iMantissa ++;
+
+  // now write out the Mantissa backwards as an integer, but include a decimal point
+  int i;
+  for (i = 0; i < NSIGFIG_DBL + 2; i++) {
+    if (i == NSIGFIG_DBL) {
+      output[NSIGFIG_DBL + 2 - i] = '.';
+      continue;
+    }
+    output[NSIGFIG_DBL + 2 - i] = '0' + iMantissa % 10;
+    iMantissa = iMantissa / 10;
+  }
+    
+  output[NSIGFIG_DBL + 3] = 'e';
+  output[NSIGFIG_DBL + 4] = isPositiveExp ? '+' : '-';
+
+  iExponent = abs(iExponent);
+
+  for (i = 0; i < NEXPFIG_DBL; i++) {
+    output[NSIGFIG_DBL + 4 + NEXPFIG_DBL - i] = '0' + iExponent % 10;
+    iExponent = iExponent / 10;
+  }
+  output[NSIGFIG_DBL + NEXPFIG_DBL + 5] = 0;
+  
+  return NSIGFIG_DBL + NEXPFIG_DBL + 5;
+}
Index: /trunk/Ohana/src/libohana/test/print_floats.c
===================================================================
--- /trunk/Ohana/src/libohana/test/print_floats.c	(revision 39040)
+++ /trunk/Ohana/src/libohana/test/print_floats.c	(revision 39040)
@@ -0,0 +1,123 @@
+# include "ohana.h"
+# include "tap_ohana.h"
+
+# define NTESTS 300000
+
+void test_float (float value) {
+  char output[128], string[128];
+
+  int Noutput = sprintf_float(output, value);
+  ok (Noutput == strlen(output), "right length");
+  sprintf (string, "%+14.7e", value);
+  ok (!strcmp (output, string), "right format");
+
+  if (strcmp (output, string)) {
+    fprintf (stderr, "output: %s, string: %s\n", output, string);
+  }
+  return;
+}
+
+void test_double (double value) {
+  char output[128], string[128];
+
+  int Noutput = sprintf_double(output, value);
+  ok (Noutput == strlen(output), "right length");
+  sprintf (string, "%+21.14e", value);
+  ok (!strcmp (output, string), "right format");
+
+  if (strcmp (output, string)) {
+    fprintf (stderr, "output: %s, string: %s\n", output, string);
+  }
+  return;
+}
+
+int main (void) {
+
+  plan_tests (20);
+
+  diag ("libohana print_float.c tests");
+
+  /*** sprint_float ***/
+  if (1) {
+    int Noutput;
+    char output[128];
+
+    // do a bunch of special values:
+    Noutput = sprintf_float(output, 0.0);
+    ok (Noutput == strlen(output), "right length for 0.0");
+    
+    test_float (1.0);
+    test_float (10.0);
+    test_float (100.0);
+
+    test_float (0.1);
+    test_float (0.01);
+    test_float (0.001);
+
+    // init with a fixed seed:
+    srand48(0);
+
+    int i;
+    float value;
+    for (i = 0; i < 1000; i++) {
+      value = 1e7 * (drand48() - 0.5);
+      test_float (value);
+    }
+
+    INITTIME;
+    for (i = 0; i < NTESTS; i++) {
+      value = 1e7 * (drand48() - 0.5);
+      sprintf_float (output, value);
+    }
+    MARKTIME("convert %d floats with sprintf_float: %f\n", NTESTS, dtime);
+
+    gettimeofday (&startTimer, (void *) NULL);
+    for (i = 0; i < NTESTS; i++) {
+      value = 1e7 * (drand48() - 0.5);
+      sprintf (output, "%+14.7e", value);
+    }
+    MARKTIME("convert %d float with sprintf: %f\n", NTESTS, dtime);
+  }
+  
+  /*** sprint_double ***/
+  if (1) {
+    int Noutput;
+    char output[128];
+
+    // do a bunch of special values:
+    Noutput = sprintf_double(output, 0.0);
+    ok (Noutput == strlen(output), "right length for 0.0");
+    
+    test_double (1.0);
+    test_double (10.0);
+    test_double (100.0);
+    test_double (0.1);
+    test_double (0.01);
+    test_double (0.001);
+
+    // init with a fixed seed:
+    srand48(0);
+    
+    int i;
+    double value;
+    for (i = 0; i < 1000; i++) {
+      value = 1e15 * (drand48() - 0.5);
+      test_double (value);
+    }
+
+    INITTIME;
+    for (i = 0; i < NTESTS; i++) {
+      value = 1e15 * (drand48() - 0.5);
+      sprintf_double (output, value);
+    }
+    MARKTIME("convert %d doubles with sprintf_double: %f\n", NTESTS, dtime);
+
+    gettimeofday (&startTimer, (void *) NULL);
+    for (i = 0; i < NTESTS; i++) {
+      value = 1e15 * (drand48() - 0.5);
+      sprintf (output, "%+21.14e", value);
+    }
+    MARKTIME("convert %d doubles with sprintf: %f\n", NTESTS, dtime);
+  }
+  return exit_status();
+}
