24
#include <drizzled/server_includes.h>
24
#include "mysql_priv.h"
25
26
#include "sql_sort.h"
26
#include <drizzled/drizzled_error_messages.h>
28
/// How to write record_ref.
29
#define WRITE_REF(file,from) \
30
if (my_b_write((file),(uchar*) (from),param->ref_length)) \
28
33
/* functions defined in this file */
30
static char **make_char_array(char **old_pos, register uint32_t fields,
31
uint32_t length, myf my_flag);
32
static unsigned char *read_buffpek_from_file(IO_CACHE *buffer_file, uint32_t count,
35
static char **make_char_array(char **old_pos, register uint fields,
36
uint length, myf my_flag);
37
static uchar *read_buffpek_from_file(IO_CACHE *buffer_file, uint count,
34
39
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
35
unsigned char * *sort_keys, IO_CACHE *buffer_file,
40
uchar * *sort_keys, IO_CACHE *buffer_file,
36
41
IO_CACHE *tempfile,IO_CACHE *indexfile);
37
static int write_keys(SORTPARAM *param,unsigned char * *sort_keys,
38
uint32_t count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
39
static void make_sortkey(SORTPARAM *param,unsigned char *to, unsigned char *ref_pos);
42
static int write_keys(SORTPARAM *param,uchar * *sort_keys,
43
uint count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
44
static void make_sortkey(SORTPARAM *param,uchar *to, uchar *ref_pos);
40
45
static void register_used_fields(SORTPARAM *param);
41
static int merge_index(SORTPARAM *param,unsigned char *sort_buffer,
46
static int merge_index(SORTPARAM *param,uchar *sort_buffer,
43
uint32_t maxbuffer,IO_CACHE *tempfile,
48
uint maxbuffer,IO_CACHE *tempfile,
44
49
IO_CACHE *outfile);
45
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count,
46
filesort_info_st *table_sort);
47
static uint32_t suffix_length(uint32_t string_length);
48
static uint32_t sortlength(THD *thd, SORT_FIELD *sortorder, uint32_t s_length,
50
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count,
51
FILESORT_INFO *table_sort);
52
static uint suffix_length(ulong string_length);
53
static uint sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
49
54
bool *multi_byte_charset);
50
55
static SORT_ADDON_FIELD *get_addon_fields(THD *thd, Field **ptabfield,
51
uint32_t sortlength, uint32_t *plength);
56
uint sortlength, uint *plength);
52
57
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
56
61
Creates a set of pointers that can be used to read the rows
87
92
examined_rows will be set to number of examined rows
90
ha_rows filesort(THD *thd, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
95
ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
91
96
SQL_SELECT *select, ha_rows max_rows,
92
97
bool sort_positions, ha_rows *examined_rows)
95
uint32_t memavl, min_sort_memory;
100
ulong memavl, min_sort_memory;
98
103
ha_rows records= HA_POS_ERROR;
99
unsigned char **sort_keys= 0;
104
uchar **sort_keys= 0;
100
105
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
102
107
bool multi_byte_charset;
104
filesort_info_st table_sort;
105
TableList *tab= table->pos_in_table_list;
109
FILESORT_INFO table_sort;
110
TABLE_LIST *tab= table->pos_in_table_list;
106
111
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
108
DRIZZLE_FILESORT_START();
113
MYSQL_FILESORT_START();
111
116
Release InnoDB's adaptive hash index latch (if holding) before
200
205
memavl= thd->variables.sortbuff_size;
201
min_sort_memory= cmax((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
206
min_sort_memory= max(MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
202
207
while (memavl >= min_sort_memory)
205
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
206
param.keys=(uint32_t) cmin(records+1, keys);
210
ulong keys= memavl/(param.rec_length+sizeof(char*));
211
param.keys=(uint) min(records+1, keys);
207
212
if ((table_sort.sort_keys=
208
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
213
(uchar **) make_char_array((char **) table_sort.sort_keys,
209
214
param.keys, param.rec_length, MYF(0))))
211
216
old_memavl=memavl;
229
234
&tempfile, selected_records_file)) ==
232
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
237
maxbuffer= (uint) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
234
239
if (maxbuffer == 0) // The whole set is in memory
236
if (save_index(¶m,sort_keys,(uint32_t) records, &table_sort))
241
if (save_index(¶m,sort_keys,(uint) records, &table_sort))
241
246
if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer)
243
if (table_sort.buffpek)
244
free(table_sort.buffpek);
248
x_free(table_sort.buffpek);
245
249
table_sort.buffpek= 0;
247
251
if (!(table_sort.buffpek=
248
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
252
(uchar *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
249
253
table_sort.buffpek)))
251
255
buffpek= (BUFFPEK *) table_sort.buffpek;
266
270
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
267
271
param.rec_length-1);
268
272
maxbuffer--; // Offset from 0
269
if (merge_many_buff(¶m,(unsigned char*) sort_keys,buffpek,&maxbuffer,
273
if (merge_many_buff(¶m,(uchar*) sort_keys,buffpek,&maxbuffer,
272
276
if (flush_io_cache(&tempfile) ||
273
277
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
275
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
279
if (merge_index(¶m,(uchar*) sort_keys,buffpek,maxbuffer,&tempfile,
313
314
MYF(ME_ERROR+ME_WAITTANG));
315
316
statistic_add(thd->status_var.filesort_rows,
316
(uint32_t) records, &LOCK_status);
317
(ulong) records, &LOCK_status);
317
318
*examined_rows= param.examined_rows;
318
memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
319
DRIZZLE_FILESORT_END();
319
memcpy(&table->sort, &table_sort, sizeof(FILESORT_INFO));
320
MYSQL_FILESORT_END();
320
321
return(error ? HA_POS_ERROR : records);
324
void filesort_free_buffers(Table *table, bool full)
325
void filesort_free_buffers(TABLE *table, bool full)
326
327
if (table->sort.record_pointers)
328
free((unsigned char*) table->sort.record_pointers);
329
my_free((uchar*) table->sort.record_pointers,MYF(0));
329
330
table->sort.record_pointers=0;
333
334
if (table->sort.sort_keys )
335
if ((unsigned char*) table->sort.sort_keys)
336
free((unsigned char*) table->sort.sort_keys);
336
x_free((uchar*) table->sort.sort_keys);
337
337
table->sort.sort_keys= 0;
339
339
if (table->sort.buffpek)
341
if ((unsigned char*) table->sort.buffpek)
342
free((unsigned char*) table->sort.buffpek);
341
x_free((uchar*) table->sort.buffpek);
343
342
table->sort.buffpek= 0;
344
343
table->sort.buffpek_len= 0;
347
346
if (table->sort.addon_buf)
349
free((char *) table->sort.addon_buf);
350
free((char *) table->sort.addon_field);
348
my_free((char *) table->sort.addon_buf, MYF(0));
349
my_free((char *) table->sort.addon_field, MYF(MY_ALLOW_ZERO_PTR));
351
350
table->sort.addon_buf=0;
352
351
table->sort.addon_field=0;
356
355
/** Make a array of string pointers. */
358
static char **make_char_array(char **old_pos, register uint32_t fields,
359
uint32_t length, myf my_flag)
357
static char **make_char_array(char **old_pos, register uint fields,
358
uint length, myf my_flag)
361
360
register char **pos;
365
(old_pos= (char**) my_malloc((uint32_t) fields*(length+sizeof(char*)),
364
(old_pos= (char**) my_malloc((uint) fields*(length+sizeof(char*)),
368
367
pos=old_pos; char_pos=((char*) (pos+fields)) -length;
376
375
/** Read 'count' number of buffer pointers into memory. */
378
static unsigned char *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint32_t count,
377
static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count,
381
uint32_t length= sizeof(BUFFPEK)*count;
382
unsigned char *tmp= buf;
380
ulong length= sizeof(BUFFPEK)*count;
383
382
if (count > UINT_MAX/sizeof(BUFFPEK))
384
383
return 0; /* sizeof(BUFFPEK)*count will overflow */
386
tmp= (unsigned char *)my_malloc(length, MYF(MY_WME));
385
tmp= (uchar *)my_malloc(length, MYF(MY_WME));
389
388
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
390
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
389
my_b_read(buffpek_pointers, (uchar*) tmp, length))
391
my_free((char*) tmp, MYF(0));
437
436
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
438
unsigned char **sort_keys,
439
438
IO_CACHE *buffpek_pointers,
440
439
IO_CACHE *tempfile, IO_CACHE *indexfile)
442
441
int error,flag,quick_select;
443
uint32_t idx,indexpos,ref_length;
444
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
442
uint idx,indexpos,ref_length;
443
uchar *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
447
446
THD *thd= current_thd;
448
447
volatile THD::killed_state *killed= &thd->killed;
621
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
617
write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
622
618
IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
624
620
size_t sort_length, rec_length;
628
624
sort_length= param->sort_length;
629
625
rec_length= param->rec_length;
630
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
626
my_string_ptr_sort((uchar*) sort_keys, (uint) count, sort_length);
631
627
if (!my_b_inited(tempfile) &&
632
628
open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
638
634
buffpek.file_pos= my_b_tell(tempfile);
639
635
if ((ha_rows) count > param->max_rows)
640
count=(uint32_t) param->max_rows; /* purecov: inspected */
636
count=(uint) param->max_rows; /* purecov: inspected */
641
637
buffpek.count=(ha_rows) count;
642
638
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
643
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
639
if (my_b_write(tempfile, (uchar*) *sort_keys, (uint) rec_length))
645
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
641
if (my_b_write(buffpek_pointers, (uchar*) &buffpek, sizeof(buffpek)))
758
754
if (sort_field->need_strxnfrm)
760
756
char *from=(char*) res->ptr();
762
if ((unsigned char*) from == to)
758
if ((uchar*) from == to)
764
760
set_if_smaller(length,sort_field->length);
765
761
memcpy(param->tmp_buffer,from,length);
766
762
from=param->tmp_buffer;
768
764
tmp_length= my_strnxfrm(cs,to,sort_field->length,
769
(unsigned char*) from, length);
765
(uchar*) from, length);
770
766
assert(tmp_length == sort_field->length);
774
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
770
my_strnxfrm(cs,(uchar*)to,length,(const uchar*)res->ptr(),length);
775
771
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
785
781
if (item->null_value)
788
memset(to-1, 0, sort_field->length+1);
784
bzero((char*) to-1,sort_field->length+1);
791
memset(to, 0, sort_field->length);
787
bzero((char*) to,sort_field->length);
796
to[7]= (unsigned char) value;
797
to[6]= (unsigned char) (value >> 8);
798
to[5]= (unsigned char) (value >> 16);
799
to[4]= (unsigned char) (value >> 24);
800
to[3]= (unsigned char) (value >> 32);
801
to[2]= (unsigned char) (value >> 40);
802
to[1]= (unsigned char) (value >> 48);
803
if (item->unsigned_flag) /* Fix sign */
804
to[0]= (unsigned char) (value >> 56);
806
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
792
#if SIZEOF_LONG_LONG > 4
793
to[7]= (uchar) value;
794
to[6]= (uchar) (value >> 8);
795
to[5]= (uchar) (value >> 16);
796
to[4]= (uchar) (value >> 24);
797
to[3]= (uchar) (value >> 32);
798
to[2]= (uchar) (value >> 40);
799
to[1]= (uchar) (value >> 48);
800
if (item->unsigned_flag) /* Fix sign */
801
to[0]= (uchar) (value >> 56);
803
to[0]= (uchar) (value >> 56) ^ 128; /* Reverse signbit */
805
to[3]= (uchar) value;
806
to[2]= (uchar) (value >> 8);
807
to[1]= (uchar) (value >> 16);
808
if (item->unsigned_flag) /* Fix sign */
809
to[0]= (uchar) (value >> 24);
811
to[0]= (uchar) (value >> 24) ^ 128; /* Reverse signbit */
809
815
case DECIMAL_RESULT:
882
888
nulls[addonf->null_offset]|= addonf->null_bit;
883
889
#ifdef HAVE_purify
884
memset(to, 0, addonf->length);
890
bzero(to, addonf->length);
889
895
#ifdef HAVE_purify
890
unsigned char *end= field->pack(to, field->ptr);
891
uint32_t length= (uint32_t) ((to + addonf->length) - end);
896
uchar *end= field->pack(to, field->ptr);
897
uint length= (uint) ((to + addonf->length) - end);
892
898
assert((int) length >= 0);
894
memset(end, 0, length);
896
902
(void) field->pack(to, field->ptr);
953
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
954
filesort_info_st *table_sort)
959
static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count,
960
FILESORT_INFO *table_sort)
956
uint32_t offset,res_length;
962
uint offset,res_length;
959
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
965
my_string_ptr_sort((uchar*) sort_keys, (uint) count, param->sort_length);
960
966
res_length= param->res_length;
961
967
offset= param->rec_length-res_length;
962
968
if ((ha_rows) count > param->max_rows)
963
count=(uint32_t) param->max_rows;
969
count=(uint) param->max_rows;
964
970
if (!(to= table_sort->record_pointers=
965
(unsigned char*) my_malloc(res_length*count, MYF(MY_WME))))
971
(uchar*) my_malloc(res_length*count, MYF(MY_WME))))
966
972
return(1); /* purecov: inspected */
967
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
973
for (uchar **end= sort_keys+count ; sort_keys != end ; sort_keys++)
969
975
memcpy(to, *sort_keys+offset, res_length);
976
982
/** Merge buffers to make < MERGEBUFF2 buffers. */
978
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
979
BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
984
int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
985
BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file)
982
988
IO_CACHE t_file2,*from_file,*to_file,*temp;
983
989
BUFFPEK *lastbuff;
1029
1035
Read data to buffer.
1032
(uint32_t)-1 if something goes wrong
1038
(uint)-1 if something goes wrong
1035
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1036
uint32_t rec_length)
1041
uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1038
register uint32_t count;
1044
register uint count;
1041
if ((count=(uint32_t) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
1047
if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
1043
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1044
return((uint32_t) -1); /* purecov: inspected */
1049
if (pread(fromfile->file,(uchar*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1050
return((uint) -1); /* purecov: inspected */
1045
1051
buffpek->key=buffpek->base;
1046
1052
buffpek->file_pos+= length; /* New filepos */
1047
1053
buffpek->count-= count;
1062
1068
@param[in] key_length key length
1065
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint32_t key_length)
1071
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length)
1067
unsigned char *reuse_end= reuse->base + reuse->max_keys * key_length;
1068
for (uint32_t i= 0; i < queue->elements; ++i)
1073
uchar *reuse_end= reuse->base + reuse->max_keys * key_length;
1074
for (uint i= 0; i < queue->elements; ++i)
1070
1076
BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
1071
1077
if (bp->base + bp->max_keys * key_length == reuse->base)
1105
1111
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
1106
IO_CACHE *to_file, unsigned char *sort_buffer,
1112
IO_CACHE *to_file, uchar *sort_buffer,
1107
1113
BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1111
uint32_t rec_length,res_length,offset;
1117
uint rec_length,res_length,offset;
1112
1118
size_t sort_length;
1114
1120
ha_rows max_rows,org_max_rows;
1115
1121
my_off_t to_start_filepos;
1116
unsigned char *strpos;
1117
1123
BUFFPEK *buffpek;
1119
1125
qsort2_cmp cmp;
1133
1139
res_length= param->res_length;
1134
1140
sort_length= param->sort_length;
1135
1141
offset= rec_length-res_length;
1136
maxcount= (uint32_t) (param->keys/((uint32_t) (Tb-Fb) +1));
1142
maxcount= (ulong) (param->keys/((uint) (Tb-Fb) +1));
1137
1143
to_start_filepos= my_b_tell(to_file);
1138
strpos= (unsigned char*) sort_buffer;
1144
strpos= (uchar*) sort_buffer;
1139
1145
org_max_rows=max_rows= param->max_rows;
1141
1147
/* The following will fire if there is not enough space in sort_buffer */
1151
1157
cmp= get_ptr_compare(sort_length);
1152
1158
first_cmp_arg= (void*) &sort_length;
1154
if (init_queue(&queue, (uint32_t) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
1160
if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
1155
1161
(queue_compare) cmp, first_cmp_arg))
1156
1162
return(1); /* purecov: inspected */
1157
1163
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1159
1165
buffpek->base= strpos;
1160
1166
buffpek->max_keys= maxcount;
1161
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1167
strpos+= (uint) (error= (int) read_to_buffer(from_file, buffpek,
1163
1169
if (error == -1)
1164
1170
goto err; /* purecov: inspected */
1165
1171
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1166
queue_insert(&queue, (unsigned char*) buffpek);
1172
queue_insert(&queue, (uchar*) buffpek);
1169
1175
if (param->unique_buff)
1206
1212
if (cmp) // Remove duplicates
1208
1214
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1209
(unsigned char**) &buffpek->key))
1215
(uchar**) &buffpek->key))
1210
1216
goto skip_duplicate;
1211
memcpy(param->unique_buff, buffpek->key, rec_length);
1217
memcpy(param->unique_buff, (uchar*) buffpek->key, rec_length);
1215
if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1221
if (my_b_write(to_file,(uchar*) buffpek->key, rec_length))
1217
1223
error=1; goto err; /* purecov: inspected */
1222
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1228
if (my_b_write(to_file, (uchar*) buffpek->key+offset, res_length))
1224
1230
error=1; goto err; /* purecov: inspected */
1269
1275
if ((ha_rows) buffpek->mem_count > max_rows)
1270
1276
{ /* Don't write too many records */
1271
buffpek->mem_count= (uint32_t) max_rows;
1277
buffpek->mem_count= (uint) max_rows;
1272
1278
buffpek->count= 0; /* Don't read more */
1274
1280
max_rows-= buffpek->mem_count;
1277
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1283
if (my_b_write(to_file,(uchar*) buffpek->key,
1278
1284
(rec_length*buffpek->mem_count)))
1280
1286
error= 1; goto err; /* purecov: inspected */
1310
1316
/* Do a merge to output-file (save only positions) */
1312
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1313
BUFFPEK *buffpek, uint32_t maxbuffer,
1318
static int merge_index(SORTPARAM *param, uchar *sort_buffer,
1319
BUFFPEK *buffpek, uint maxbuffer,
1314
1320
IO_CACHE *tempfile, IO_CACHE *outfile)
1316
1322
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1569
1579
#define DBL_EXP_DIG (sizeof(double)*8-DBL_MANT_DIG)
1571
void change_double_for_sort(double nr,unsigned char *to)
1581
void change_double_for_sort(double nr,uchar *to)
1573
unsigned char *tmp=(unsigned char*) to;
1583
uchar *tmp=(uchar*) to;
1575
1585
{ /* Change to zero string */
1576
tmp[0]=(unsigned char) 128;
1577
memset(tmp+1, 0, sizeof(nr)-1);
1587
bzero((char*) tmp+1,sizeof(nr)-1);
1581
1591
#ifdef WORDS_BIGENDIAN
1582
memcpy(tmp,&nr,sizeof(nr));
1592
memcpy_fixed(tmp,&nr,sizeof(nr));
1585
unsigned char *ptr= (unsigned char*) &nr;
1595
uchar *ptr= (uchar*) &nr;
1586
1596
#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
1587
1597
tmp[0]= ptr[3]; tmp[1]=ptr[2]; tmp[2]= ptr[1]; tmp[3]=ptr[0];
1588
1598
tmp[4]= ptr[7]; tmp[5]=ptr[6]; tmp[6]= ptr[5]; tmp[7]=ptr[4];
1595
1605
if (tmp[0] & 128) /* Negative */
1596
1606
{ /* make complement */
1598
1608
for (i=0 ; i < sizeof(nr); i++)
1599
tmp[i]=tmp[i] ^ (unsigned char) 255;
1609
tmp[i]=tmp[i] ^ (uchar) 255;
1602
1612
{ /* Set high and move exponent one up */
1603
uint16_t exp_part=(((uint16_t) tmp[0] << 8) | (uint16_t) tmp[1] |
1605
exp_part+= (uint16_t) 1 << (16-1-DBL_EXP_DIG);
1606
tmp[0]= (unsigned char) (exp_part >> 8);
1607
tmp[1]= (unsigned char) exp_part;
1613
ushort exp_part=(((ushort) tmp[0] << 8) | (ushort) tmp[1] |
1615
exp_part+= (ushort) 1 << (16-1-DBL_EXP_DIG);
1616
tmp[0]= (uchar) (exp_part >> 8);
1617
tmp[1]= (uchar) exp_part;