trying to fix undefined symbol problems people are having
[comedilib.git] / lib / range.c
1 /*
2     lib/range.c
3     functions to manipulate physical unit conversion
4
5     COMEDILIB - Linux Control and Measurement Device Interface Library
6     Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org>
7
8     This library is free software; you can redistribute it and/or
9     modify it under the terms of the GNU Lesser General Public
10     License as published by the Free Software Foundation, version 2.1
11     of the License.
12
13     This library is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16     Lesser General Public License for more details.
17
18     You should have received a copy of the GNU Lesser General Public
19     License along with this library; if not, write to the Free Software
20     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
21     USA.
22 */
23
24 #include <stdio.h>
25
26 #define __USE_GNU
27
28 #include <math.h>
29 #include <stdlib.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <sys/ioctl.h>
35 #include <errno.h>
36 #include <string.h>
37
38 #include "libinternal.h"
39
40
41 /* sometimes we can't find a definition of NAN */
42
43 #ifndef NAN
44 #define NAN \
45   (__extension__ ((union { unsigned char __c[8];                              \
46                            double __d; })                                     \
47                   { { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f } }).__d)
48 #endif
49
50
51 static enum comedi_oor_behavior comedi_oor_is_nan = COMEDI_OOR_NAN;
52
53 EXPORT_ALIAS_DEFAULT(_comedi_set_global_oor_behavior,comedi_set_global_oor_behavior,0.7.18);
54 enum comedi_oor_behavior _comedi_set_global_oor_behavior(
55         enum comedi_oor_behavior behavior)
56 {
57         int old_behavior=comedi_oor_is_nan;
58
59         comedi_oor_is_nan=behavior;
60
61         return old_behavior;
62 }
63
64
65 EXPORT_ALIAS_DEFAULT(_comedi_to_phys,comedi_to_phys,0.7.18);
66 double _comedi_to_phys(lsampl_t data,comedi_range *rng,lsampl_t maxdata)
67 {
68         double x;
69
70         if(!rng)return NAN;
71         if(!maxdata)return NAN;
72
73         if(comedi_oor_is_nan==COMEDI_OOR_NAN && (data==0 || data==maxdata))
74                 return NAN;
75
76         x=data;
77         x/=maxdata;
78         x*=(rng->max-rng->min);
79         x+=rng->min;
80
81         return x;
82 }
83
84 EXPORT_ALIAS_DEFAULT(_comedi_from_phys,comedi_from_phys,0.7.18);
85 lsampl_t _comedi_from_phys(double data,comedi_range *rng,lsampl_t maxdata)
86 {
87         double s;
88
89         if(!rng)return 0;
90         if(!maxdata)return 0;
91
92         s=(data-rng->min)/(rng->max-rng->min)*maxdata;
93         if(s<0)return 0;
94         if(s>maxdata)return maxdata;
95
96         return (lsampl_t)(floor(s+0.5));
97 }
98
99 EXPORT_ALIAS_DEFAULT(_comedi_find_range,comedi_find_range,0.7.18);
100 int _comedi_find_range(comedi_t *it,unsigned int subd,unsigned int chan,unsigned int unit,double min,double max)
101 {
102         unsigned int range_type;
103         int best;
104         comedi_range *range_ptr,*best_ptr;
105         int i;
106         
107         if(!valid_chan(it,subd,chan))return -1;
108
109         range_type=comedi_get_rangetype(it,subd,chan);
110         best=-1;
111         best_ptr=NULL;
112         for(i=0;i<RANGE_LENGTH(range_type);i++){
113                 range_ptr=comedi_get_range(it,subd,chan,i);
114                 if(range_ptr->min<=min && range_ptr->max>=max){
115                         if(best<0 || (range_ptr->max-range_ptr->min) < 
116                            (best_ptr->max-best_ptr->min)){
117                                 best=i;
118                                 best_ptr=range_ptr;
119                         }
120                 }
121         }
122         return best;
123 }
124
125 EXPORT_ALIAS_DEFAULT(_comedi_get_n_ranges,comedi_get_n_ranges,0.7.18);
126 int _comedi_get_n_ranges(comedi_t *it,unsigned int subd,unsigned int chan)
127 {
128         unsigned int range_type;
129
130         if(!valid_chan(it,subd,chan))return -1;
131
132         range_type=comedi_get_rangetype(it,subd,chan);
133         return RANGE_LENGTH(range_type);
134 }
135
136 EXPORT_ALIAS_DEFAULT(_comedi_range_is_chan_specific,comedi_range_is_chan_specific,0.7.18);
137 int _comedi_range_is_chan_specific(comedi_t *it,unsigned int subd)
138 {
139         return (it->subdevices[subd].subd_flags&SDF_RANGETYPE)?1:0;
140 }
141
142 EXPORT_ALIAS_DEFAULT(_comedi_sampl_to_phys,comedi_sampl_to_phys,0.7.18);
143 int _comedi_sampl_to_phys(double *dest, int dst_stride, sampl_t *src,
144         int src_stride, comedi_range *rng, lsampl_t maxdata, int n)
145 {
146         int oor = 0;
147         int i;
148         double mult;
149
150         if(!rng)return -1;
151         if(!maxdata)return -1;
152
153         mult = (rng->max-rng->min)/maxdata;
154         if(comedi_oor_is_nan==COMEDI_OOR_NAN){
155                 for(i=0;i<n;i++){
156                         if(*src==0 || *src==maxdata){
157                                 oor++;
158                                 *dest=NAN;
159                         }else{
160                                 *dest = rng->min + mult*(*src);
161                         }
162                         dest = ((void *)dest) + dst_stride;
163                         src = ((void *)src) + src_stride;
164                 }
165         }else{
166                 for(i=0;i<n;i++){
167                         if(*src==0 || *src==maxdata){
168                                 oor++;
169                         }
170                         *dest = rng->min + mult*(*src);
171                         dest = ((void *)dest) + dst_stride;
172                         src = ((void *)src) + src_stride;
173                 }
174         }
175
176         return oor;
177 }
178
179 EXPORT_ALIAS_DEFAULT(_comedi_sampl_from_phys,comedi_sampl_from_phys,0.7.18);
180 int _comedi_sampl_from_phys(sampl_t *dest,int dst_stride,double *src,
181         int src_stride, comedi_range *rng, lsampl_t maxdata, int n)
182 {
183         int oor = 0;
184         double mult;
185         int i;
186
187         if(!rng)return -1;
188         if(!maxdata)return -1;
189
190         mult = (maxdata+1)/(rng->max-rng->min);
191         for(i=0;i<n;i++){
192                 *dest=mult*(*src-rng->min);
193                 if(*src<rng->min){
194                         *dest=0;
195                         oor++;
196                 }
197                 if(*src>rng->min){
198                         *dest=maxdata;
199                         oor++;
200                 }
201                 dest = ((void *)dest) + dst_stride;
202                 src = ((void *)src) + src_stride;
203         }
204
205         return oor;
206 }
207