Ticket #468: 5835-fpu-status.patch

File 5835-fpu-status.patch, 5.2 KB (added by bober, 15 years ago)

x86 specific fpu stuff -- see ticket discussion (this should NOT be included in sage)

  • new file sage/misc/fpu.pyx

    # HG changeset patch
    # User Jonathan Bober <bober@umich.edu>
    # Date 1187893106 14400
    # Node ID dbb16972b9a8b9e2531a9e30610ae7cb2565289c
    # Parent  76e3ea40f96aff4022ef96f9ea323fe07f43e3d5
    x86 specific code to check/set the fpu precision. Example usage:
    
    sage: import sage.misc.fpu as fpu
    sage: fpu.get_precision()
    'extended'
    sage: fpu.set_double_precision()
    sage: fpu.get_precision()
    'double'
    sage: fpu.set_single_precision()
    sage: fpu.get_precision()
    'single'
    sage: fpu.set_extended_precision()
    sage: fpu.get_precision()
    'extended'
    
    diff -r 76e3ea40f96a -r dbb16972b9a8 sage/misc/fpu.pyx
    - +  
     1cdef extern from "fpu_status.h":
     2    int set_fpu_double_precision()
     3    int set_fpu_extended_precision()
     4    int set_fpu_single_precision()
     5    int get_fpu_precision()
     6    void print_fpu_precision()
     7
     8def set_double_precision():
     9    set_fpu_double_precision()
     10
     11def set_extended_precision():
     12    set_fpu_extended_precision()
     13
     14def set_single_precision():
     15    set_fpu_single_precision()
     16
     17def print_precision():
     18    print_fpu_precision()
     19
     20def get_precision():
     21    i = get_fpu_precision()
     22    if i == 0:
     23        return "single"
     24    elif i == 2:
     25        return "double"
     26    elif i == 3:
     27        return "extended"
     28    else:
     29        return "error"
  • new file sage/misc/fpu_status.c

    diff -r 76e3ea40f96a -r dbb16972b9a8 sage/misc/fpu_status.c
    - +  
     1#include <stdio.h>
     2
     3/* fpu control word:
     4
     5111 1 11 00 00000000
     6543 2 10 98 76543210
     7^^^ reserved
     8    ^ infinity bit
     9      ^^ rounding control
     10         ^^ precision control
     11
     12         then: ES, SF, PM, UM, OM, ZM, DM, IM
     13
     14precision control
     15    00 -- single precision
     16    01 -- reserved
     17    10 -- double precision
     18    11 -- extended precision
     19*/
     20
     21static inline int set_fpu_double_precision() {
     22    volatile unsigned short old_cw, new_cw;
     23    asm volatile ("fnstcw %0":"=m" (old_cw));
     24    new_cw = (old_cw & ~0x300) | 0x200;
     25    asm volatile ("fldcw %0": :"m" (new_cw));
     26    return old_cw;
     27}
     28
     29static inline int set_fpu_single_precision() {
     30    volatile unsigned short old_cw, new_cw;
     31    asm volatile ("fnstcw %0":"=m" (old_cw));
     32    new_cw = (old_cw & ~0x300);
     33    asm volatile ("fldcw %0": :"m" (new_cw));
     34    return old_cw;
     35}
     36
     37static inline int set_fpu_extended_precision() {
     38  volatile unsigned short old_cw, new_cw;
     39  asm volatile ("fnstcw %0":"=m" (old_cw));
     40  //__new_cw = (__old_cw & ~0x200) | 0x300;
     41  new_cw = old_cw | 0x300;
     42  asm volatile ("fldcw %0": :"m" (new_cw));
     43  return old_cw;
     44}
     45
     46static inline void set_fpu_control_word(int cw) {
     47    asm volatile ("fldcw %0": :"m" (cw));
     48}
     49
     50void print_fpu_precision() {
     51    volatile unsigned short control_word;
     52    asm volatile ("fnstcw %0":"=m" (control_word));
     53    short precision_bits = (control_word >> 8) & 3;
     54    if(precision_bits == 0) { printf("single\n"); }
     55    else if(precision_bits == 2) { printf("double\n"); }
     56    else if(precision_bits == 3) { printf("extended\n"); }
     57    else {
     58        printf("something wierd happened. precision_bits was %d\n", precision_bits);
     59    }
     60}
     61
     62int get_fpu_precision() {
     63    volatile unsigned short control_word;
     64    asm volatile ("fnstcw %0":"=m" (control_word));
     65    short precision_bits = (control_word >> 8) & 3;
     66    return (int)precision_bits;
     67}
     68
     69int main() {
     70    int control_word = set_fpu_double_precision();
     71    print_fpu_precision();
     72    set_fpu_extended_precision();
     73    print_fpu_precision();
     74    set_fpu_single_precision();
     75    print_fpu_precision();
     76   
     77    set_fpu_control_word(control_word);
     78
     79    print_fpu_precision();
     80
     81    return 0;
     82}
  • new file sage/misc/fpu_status.h

    diff -r 76e3ea40f96a -r dbb16972b9a8 sage/misc/fpu_status.h
    - +  
     1static inline int set_fpu_double_precision() {
     2    volatile unsigned short old_cw, new_cw;
     3    asm volatile ("fnstcw %0":"=m" (old_cw));
     4    new_cw = (old_cw & ~0x300) | 0x200;
     5    asm volatile ("fldcw %0": :"m" (new_cw));
     6    return old_cw;
     7}
     8
     9static inline int set_fpu_single_precision() {
     10    volatile unsigned short old_cw, new_cw;
     11    asm volatile ("fnstcw %0":"=m" (old_cw));
     12    new_cw = (old_cw & ~0x300);
     13    asm volatile ("fldcw %0": :"m" (new_cw));
     14    return old_cw;
     15}
     16
     17static inline int set_fpu_extended_precision() {
     18  volatile unsigned short old_cw, new_cw;
     19  asm volatile ("fnstcw %0":"=m" (old_cw));
     20  //__new_cw = (__old_cw & ~0x200) | 0x300;
     21  new_cw = old_cw | 0x300;
     22  asm volatile ("fldcw %0": :"m" (new_cw));
     23  return old_cw;
     24}
     25
     26static inline void set_fpu_control_word(int cw) {
     27    asm volatile ("fldcw %0": :"m" (cw));
     28}
     29
     30void print_fpu_precision();
     31int get_fpu_precision();
  • setup.py

    diff -r 76e3ea40f96a -r dbb16972b9a8 setup.py
    a b ext_modules = [ \ 
    629629    Extension('sage.graphs.bruhat_sn',
    630630              ['sage/graphs/bruhat_sn.pyx']
    631631              ), \
     632
     633    Extension('sage.misc.fpu',
     634              ['sage/misc/fpu.pyx',
     635               'sage/misc/fpu_status.c'],
     636              language='c')
    632637                           
    633638    ]
    634639