Mailing List Archive


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[tlug] measureTemp_hot.c: release early, release often . . . . . . . . . . (was Re: just a quick note... more to come later :))



On Thu, 27 Jul 2006 10:19:40 +0200 Michal Hajek <hajek1@example.com> wrote:

> [1] http://material.karlov.mff.cuni.cz/people/hajek/pec/

measureTemp_hot.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <getopt.h>
#include <gpib/ib.h>
#include <sys/timeb.h>
#include <time.h>
#include <math.h>
#include "lojza.h"

/*^^^ maybe constants should go in a header file, perhaps kcoefficients_inverse.h */

/* data from http://srdata.nist.gov/its90/type_k/kcoefficients_inverse.html */
/* ^^^ nice reference! */

#define A0 (-0.176004136860E-01)
#define A1 ( 0.389212049750E-01)
#define A2 ( 0.185587700320E-04)
#define A3 (-0.994575928740E-07)
#define A4 ( 0.318409457190E-09)
#define A5 (-0.560728448890E-12)
#define A6 ( 0.560750590590E-15)
#define A7 (-0.320207200030E-18)
#define A8 ( 0.971511471520E-22)
#define A9 (-0.121047212750E-25)

/* ^^^ I'm uncomfortable with the following constant names being
*  lower-case. (Making them variables would be a feeble workaround)
*  Having such similar names with upper-case names is also uncomfortable.
*  Good luck choosing better names */

#define a0 ( 0.118597600000E+00)
#define a1 (-0.118343200000E-03)
#define a2 ( 0.126968600000E+03)

#define B0 (  0.000000E+00)
#define B1 (  2.508355E+01)
#define B2 (  7.860106E-02)
#define B3 ( -2.503131E-01)
#define B4 (  8.315270E-02)
#define B5 ( -1.228034E-02)
#define B6 (  9.804036E-04)
#define B7 ( -4.413030E-05)
#define B8 (  1.057734E-06)
#define B9 ( -1.052755E-08)

#define C0 (-1.318058E+02)
#define C1 ( 4.830222E+01)
#define C2 (-1.646031E+00)
#define C3 ( 5.464731E-02)
#define C4 (-9.650715E-04)
#define C5 ( 8.802193E-06)
#define C6 (-3.110810E-08)
#define C7 ( 0.000000E+00)
#define C8 ( 0.000000E+00)
#define C9 ( 0.000000E+00)

double measureTemp_hot(double tc)
{
   char buffer[MAX_KEITHLEY_REPLY_LEN+1];

   float e2;
   float e1; /* thermocouple voltage */
   float e;
   float th;

   struct timeval time_now;

   /* MERENI VZORKU */

   /* configure K706 */

   e2 = A0
   + A1*powf(Tc,1)
   + A2*powf(Tc,2)
   + A3*powf(Tc,3)
   + A4*powf(Tc,4)
   + A5*powf(Tc,5)
   + A6*powf(Tc,6)
   + A7*powf(Tc,7)
   + A8*powf(Tc,8)
   + A9*powf(Tc,9)
   + a0*expf(a1 * powf(Tc-a2,2));

   ibwrtstr(K706Ud,"C10C13X");
   ibwrtstr(K2182Ud,"*trg");

   ibwrtstr(K2182Ud,":sense:data:fresh?");
   ibrd(K2182Ud,buffer,MAX_KEITHLEY_REPLY_LEN);
   gettimeofday(&time_now,NULL);
   buffer[ibcnt]='\0';
   ibwrtstr(K706Ud,"N10N13X");
   e1 = 1000*atof(buffer);
   e = e1 + e2;

   if (e<=20.644)
      th = B0
      + B1*powf(e,1)
      + B2*powf(e,2)
      + B3*powf(e,3)
      + B4*powf(e,4)
      + B5*powf(e,5)
      + B6*powf(e,6)
      + B7*powf(e,7)
      + B8*powf(e,8)
      + B9*powf(e,9);
   else
      th = C0
      + C1*powf(e,1)
      + C2*powf(e,2)
      + C3*powf(e,3)
      + C4*powf(e,4)
      + C5*powf(e,5)
      + C6*powf(e,6)
      + C7*powf(e,7)
      + C8*powf(e,8)
      + C9*powf(e,9);

   printf("t= %d.%06ld s \t T= %.2f C \n"
   , (int)time_now.tv_sec,time_now.tv_usec,th);
   /* ^^^ why case to an int? why not allow big values: */
   printf("t= %ld.%06ld s \t T= %.2f C \n"
   , time_now.tv_sec,time_now.tv_usec,th);

   /* ^^^ also, beware of hard tabs. They are not portable. 
   *  different programs and printers do different things with them */

   return th;
}

#if 0
don't arbitrarily restrict your constants to float.
You loose accuracy and speed, since all floats are converted to doubles
before expressions are evaluated.
avoid super long lines.
Keep in mind that the = part of <= in E<=20.644,
has little practical meaning because of the nature of
round off errors in floating point math.

It later on you are really concerned about execution speed,
consider eliminating the use of powf() function.
If it uses logarithms, it might be slow.
consider replacing the formulas that use powf() with a loop
that does simple (albeit repeated) multiplication.
Here's the incomplete ideas:

   const double c_coefficient_table[COEFFICIENT_TABLE_LEN]={
      -1.318058E+02,
       4.830222E+01,
      -1.646031E+00,
       5.464731E-02,
      -9.650715E-04,
       8.802193E-06,
      -3.110810E-08,
       0.000000E+00,
       0.000000E+00,
       0.000000E+00
   };

   if (e<=20.644)
      coefficient_table=b_coefficient_table;
   else
      coefficient_table=c_coefficient_table;

   or

   coefficient_table = (e<=20.644) ? b_coefficient_table : c_coefficient_table;

   th=0.0;
   product=1.0;
   for (i=0;i<COEFFICIENT_TABLE_LEN;i++) {
      th+=coefficient_table[i]*product;
      product*=e;
   }

   or

   double *p;

   p = (e<=20.644) ? b_coefficient_table : c_coefficient_table;

   th=0.0;
   product=1.0;
   for (i=0;i<COEFFICIENT_TABLE_LEN;i++) {
      th+=*p++*product;
      product*=e;
   }

In this case, the constants would be stored in variables,
so the names would be lower case.

Whatever you do, don't worry about speed too soon.
Make your code clear first.
Maximize clarity.
#endif


Home | Main Index | Thread Index

Home Page Mailing List Linux and Japan TLUG Members Links