Drizzled Public API Documentation

double.cc
1 /* - mode: c++ c-basic-offset: 2; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3  *
4  * Copyright (C) 2008 MySQL
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 
22 #include <config.h>
23 
24 #include <float.h>
25 #include <math.h>
26 
27 #include <algorithm>
28 
29 #include <drizzled/field/double.h>
30 #include <drizzled/error.h>
31 #include <drizzled/table.h>
32 #include <drizzled/session.h>
33 #include <drizzled/current_session.h>
34 #include <drizzled/internal/m_string.h>
35 
36 using namespace std;
37 
38 namespace drizzled
39 {
40 
41 /****************************************************************************
42  double precision floating point numbers
43 ****************************************************************************/
44 
45 int Field_double::store(const char *from,uint32_t len, const charset_info_st * const cs)
46 {
47  int error;
48  char *end;
49  double nr= my_strntod(cs,(char*) from, len, &end, &error);
50 
51  ASSERT_COLUMN_MARKED_FOR_WRITE;
52  if (error || (!len || (((uint32_t) (end-from) != len) && getTable()->in_use->count_cuted_fields)))
53  {
54  set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
55  (error ? ER_WARN_DATA_OUT_OF_RANGE : ER_WARN_DATA_TRUNCATED), 1);
56  error= error ? 1 : 2;
57  }
58  Field_double::store(nr);
59  return error;
60 }
61 
62 
63 int Field_double::store(double nr)
64 {
65  int error= truncate(&nr, DBL_MAX);
66 
67  ASSERT_COLUMN_MARKED_FOR_WRITE;
68 
69 #ifdef WORDS_BIGENDIAN
70  if (getTable()->getShare()->db_low_byte_first)
71  {
72  float8store(ptr,nr);
73  }
74  else
75 #endif
76  doublestore(ptr,nr);
77  return error;
78 }
79 
80 
81 int Field_double::store(int64_t nr, bool unsigned_val)
82 {
83  return Field_double::store(unsigned_val ? uint64_t2double((uint64_t) nr) :
84  (double) nr);
85 }
86 
87 double Field_double::val_real(void) const
88 {
89  double j;
90 
91  ASSERT_COLUMN_MARKED_FOR_READ;
92 
93 #ifdef WORDS_BIGENDIAN
94  if (getTable()->getShare()->db_low_byte_first)
95  {
96  float8get(j,ptr);
97  }
98  else
99 #endif
100  doubleget(j,ptr);
101  return j;
102 }
103 
104 int64_t Field_double::val_int(void) const
105 {
106  double j;
107  int64_t res;
108 
109  ASSERT_COLUMN_MARKED_FOR_READ;
110 
111 #ifdef WORDS_BIGENDIAN
112  if (getTable()->getShare()->db_low_byte_first)
113  {
114  float8get(j,ptr);
115  }
116  else
117 #endif
118  doubleget(j,ptr);
119  /* Check whether we fit into int64_t range */
120  if (j <= (double) INT64_MIN)
121  {
122  res= (int64_t) INT64_MIN;
123  goto warn;
124  }
125  if (j >= (double) (uint64_t) INT64_MAX)
126  {
127  res= (int64_t) INT64_MAX;
128  goto warn;
129  }
130  return (int64_t) rint(j);
131 
132 warn:
133  {
134  char buf[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
135  String tmp(buf, sizeof(buf), &my_charset_utf8_general_ci), *str;
136  str= val_str(&tmp, &tmp);
137  Session *session= getTable() ? getTable()->in_use : current_session;
138  push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
139  ER_TRUNCATED_WRONG_VALUE,
140  ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER",
141  str->c_ptr());
142  }
143  return res;
144 }
145 
146 
147 String *Field_double::val_str(String *val_buffer, String *) const
148 {
149  double nr;
150 
151  ASSERT_COLUMN_MARKED_FOR_READ;
152 
153 #ifdef WORDS_BIGENDIAN
154  if (getTable()->getShare()->db_low_byte_first)
155  {
156  float8get(nr,ptr);
157  }
158  else
159 #endif
160  doubleget(nr,ptr);
161 
162  uint32_t to_length= max(field_length, (uint32_t)DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE);
163  val_buffer->alloc(to_length);
164  char *to=(char*) val_buffer->ptr();
165  size_t len;
166 
167  if (dec >= NOT_FIXED_DEC)
168  len= internal::my_gcvt(nr, internal::MY_GCVT_ARG_DOUBLE, to_length - 1, to, NULL);
169  else
170  len= internal::my_fcvt(nr, dec, to, NULL);
171 
172  val_buffer->length((uint32_t) len);
173 
174  return val_buffer;
175 }
176 
177 int Field_double::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
178 {
179  double a,b;
180 #ifdef WORDS_BIGENDIAN
181  if (getTable()->getShare()->db_low_byte_first)
182  {
183  float8get(a,a_ptr);
184  float8get(b,b_ptr);
185  }
186  else
187 #endif
188  {
189  doubleget(a, a_ptr);
190  doubleget(b, b_ptr);
191  }
192  return (a < b) ? -1 : (a > b) ? 1 : 0;
193 }
194 
195 
196 /* The following should work for IEEE */
197 
198 void Field_double::sort_string(unsigned char *to,uint32_t )
199 {
200  double nr;
201 #ifdef WORDS_BIGENDIAN
202  if (getTable()->getShare()->db_low_byte_first)
203  {
204  float8get(nr,ptr);
205  }
206  else
207 #endif
208  doubleget(nr,ptr);
209  change_double_for_sort(nr, to);
210 }
211 
212 } /* namespace drizzled */