mathf.h は何のために有るのか

RX621のマニュアルに math.h と mathf.h が有ります。
mathf.h は、次の説明が書かれています。

<mathf.h>ではANSI 規格規定外の単精度形式の数学関数の宣言とマクロの定義をしています。
各関数はfloat 型の実引数を受け取り、float 型の値を返します。

math.h の float 型を使えば良いと思うのですが、何故 mathf.h が有るのでしょう。
「ANSI 規格規定外の単精度形式」と言うのが引っ掛かります。何か長所が有って、ルネサス独自の規格なのでしょうか。

  • リカルドさん、こんにちは。NoMaYです。

    mathf.hはH8コンパイラからCC-RXへ引き継がれたものではないでしょうか。(私の昔の投稿で調べていた__evenaccess拡張キーワードもH8コンパイラからCC-RXコンパイラへ引き継がれたものの1つのようでした。)

    Google検索: H8コンパイラ "mathf.h"
    www.google.com/search?q=H8コンパイラ+"mathf.h"

    たぶん、H8コンパイラの歴史もH8マイコンと同じぐらい歴史のあるものだと思います。

    H8 - ウィキペディア
    ja.wikipedia.org/wiki/H8

    H8/500(株式会社日立製作所「H8/500シリーズプログラミングマニュアル」第1版1988年10月) ⇒ 35年前ですね。


    特集 最新半導体技術 Hシリーズマイクロコンピュータの展開 - 日立評論 1990年12月
    www.hitachihyoron.com/jp/pdf/1990/12/1990_12_06.pdf

    私は昔のH8コンパイラのマニュアルを持っていませんけれども(たぶん製本されたものだけかと思うのですけれども)、ANSI規格前に既にmathf.hが存在していた可能性もありそうに思いました。

    リカルドさんはH8マイコンユーザでしたでしょうか?もしそうなら(そうであったなら)、改めて記憶を辿ると何か思い出すことはありませんでしょうか?

  • リカルド です。

    NoMaY さん、回答有難う御座います。

    H8のマニュアルを見て、分かって来ました。
    H8のマニュアルでは math.h のデータサイズが double で、mathf.h は float でした。

    RX621では math.h の中に次のように書かれています。

    ===== マニュアルから =======================

    ダブルアコス(ダブルD)
    フロートアコスフ(フロートD)
    ロングダブルアコスル(ロングダブルD)

    投稿したら翻訳機能が働いたのか、この部分が片仮名になってしまいました。

    スペースも削除されてしまいました。

    1行目は d o u b l e a c o s (d o u b l e d) です。

    =====================================


    mathf.h の中にも float acosf(float d) が有るので、math.h を使えば mathf.h は不要だと分かります。

    long double 用の mathl.h を作る代わりに、math.h に3種類の型を纏めたようです。


    ●調べていて、他にも疑問が出て来ました。

    ===== マニュアルから =======================

    dbl_size
    書 式 dbl_size={4 | 8}
    説 明 double 型、およびlong double 型の精度を指定します。
    dbl_size=4 を指定した場合、単精度浮動小数点型(4 バイト)として扱います。
    dbl_size=8 を指定した場合、倍精度浮動小数点型(8 バイト)として扱います。
    本オプションの省略時解釈は、dbl_size=4 です。

    =====================================

    これを読むと、double と long double は同じ精度だと分かります。
    「本オプションの省略時解釈は、dbl_size=4 です。」と言う仕様がおかしいと思うのです。
    欲しい精度によって float と double とを使い分けてプログラムを作ります。
    double で作ってみたけど不要なので float にしたいと言うオプションなら分かります。
    しかし省略時に float になってしまうのでは、何の為に double が用意されているのかと思います。

  • リカルドさん、エビスクラウンと申します。

    お考えを覆すようで申し訳ないのですが、私にはCC-RXの仕様が普通で、リカルドさんの考えの方がおかしいと思えてなりません。その理由は以下の通りです。

    リカルドさんも使われているRX621のRXv1コアが持っているFPU機能は単精度形式のみです。RXv3コアが持っている倍精度形式には対応していません。なので、全ての浮動小数点型に対して内蔵のFPUが働くようにdbl_size=4がデフォルト設定なのは当然ではないでしょうか?

    ただし、他の処理系やマイコンとの移植性を考えて、オプションを使えばdouble型とlong double型はdbl_size=8の倍精度形式とすることができる(内蔵FPUが働かず、大幅に性能が劣化するが。。。)。極自然な仕様に思えるのですが!

  • リカルドさん、こんにちは。NoMaYです。

    まず、acosf()などのfloat型系の数学関数とacosl()などのlong double型系の数学関数はC99で追加された仕様であり、C90には無かった仕様でした。H8コンパイラの最終版V7.0.0のドキュメントでは既にC99対応のオプションがありましたので、まさにmathf.hが導入された時期とH8コンパイラがC99に対応した時期とのタイミング関係は私では分かりませんけれども、mathf.hの方が先だった可能性もありそうに思いました。

    acos, acosf, acosl - cppreference.com
    ja.cppreference.com/w/c/numeric/math/acos

    ちなみに、H8コンパイラの最終版V7.0.0のインクルードフォルダを見てみたところ、C89とC99の2つのフォルダに分かれていました。そして、C89というフォルダのmath.hとmathf.hは以下の通りになっていました。そのmath.hにはacosf()などのfloat型系の数学関数はありませんでした。(他方で、C99というフォルダにはmathf.hはありませんでした。)

    HEW/Tools/Renesas/H8/7_0_0/include/C89/math.h

    /*------------------------------------------------------------------------------*/
    /* H8S,H8/300 SERIES C/C++ Compiler Ver. 7.0                                    */
    /* Copyright (C) 1994,2007 Renesas Technology Corp. and Renesas Solutions Corp. */
    /* Copyright (C) 2000 Hitachi, Ltd.                                             */
    /* Copyright (C) 1994,2007 Hitachi Information & Control Solutions, Ltd.        */
    /* All rights reserved.                                                         */
    /*------------------------------------------------------------------------------*/

    #ifndef _MATH_H
    #define _MATH_H

    #define ERANGE  1100
    #define EDOM    1101

    #ifndef HUGE_VAL
    #ifdef __FLT__
    extern const float _HUGE_VALF;
    #define HUGE_VAL _HUGE_VALF
    #else
    extern const double _HUGE_VAL;
    #define HUGE_VAL _HUGE_VAL
    #endif
    #endif

    #ifdef __cplusplus
    extern "C" {
    #endif

    #ifndef errno
    #ifdef _REENTRANT
    extern int *errno_addr(void);
    #define errno (*errno_addr())
    #else
    extern volatile int _errno;
    #define errno _errno
    #endif
    #endif

    extern double acos(double);
    extern double asin(double);
    extern double atan(double);
    extern double atan2(double, double);
    extern double cos(double);
    extern double sin(double);
    extern double tan(double);
    extern double cosh(double);
    extern double sinh(double);
    extern double tanh(double);
    extern double exp(double);
    extern double frexp(double, int *);
    extern double ldexp(double, int);
    extern double log(double);
    extern double log10(double);
    extern double modf(double, double *);
    extern double pow(double, double);
    extern double sqrt(double);
    extern double ceil(double);
    extern double fabs(double);
    extern double floor(double);
    extern double fmod(double, double);
    #ifdef __cplusplus
    }
    #endif

    #endif /* _MATH_H */

     
    HEW/Tools/Renesas/H8/7_0_0/include/C89/mathf.h

    /*------------------------------------------------------------------------------*/
    /* H8S,H8/300 SERIES C/C++ Compiler Ver. 7.0                                    */
    /* Copyright (C) 1994,2007 Renesas Technology Corp. and Renesas Solutions Corp. */
    /* Copyright (C) 2000 Hitachi, Ltd.                                             */
    /* Copyright (C) 1994,2007 Hitachi Information & Control Solutions, Ltd.        */
    /* All rights reserved.                                                         */
    /*------------------------------------------------------------------------------*/

    #ifndef _MATHF_H
    #define _MATHF_H

    #define ERANGE  1100
    #define EDOM    1101

    extern const float _HUGE_VALF;
    #define HUGE_VALF _HUGE_VALF

    #ifndef HUGE_VAL
    #ifdef __FLT__
    #define HUGE_VAL _HUGE_VALF
    #else
    extern const double _HUGE_VAL;
    #define HUGE_VAL _HUGE_VAL
    #endif
    #endif

    #ifdef __cplusplus
    extern "C" {
    #endif

    #ifndef errno
    #ifdef _REENTRANT
    extern int *errno_addr(void);
    #define errno (*errno_addr())
    #else
    extern volatile int _errno;
    #define errno _errno
    #endif
    #endif

    extern float acosf(float);
    extern float asinf(float);
    extern float atanf(float);
    extern float atan2f(float, float);
    extern float cosf(float);
    extern float sinf(float);
    extern float tanf(float);
    extern float coshf(float);
    extern float sinhf(float);
    extern float tanhf(float);
    extern float expf(float);
    extern float frexpf(float, int *);
    extern float ldexpf(float, int);
    extern float logf(float);
    extern float log10f(float);
    extern float modff(float, float *);
    extern float powf(float, float);
    extern float sqrtf(float);
    extern float ceilf(float);
    extern float fabsf(float);
    extern float floorf(float);
    extern float fmodf(float, float);
    #ifdef __cplusplus
    }
    #endif

    #endif /* _MATHF_H */

     

  • リカルド です。

    エビスクラウン さん、回答有難う御座います。
    他の人の意見も聞きたいけど、出て来ませんね。

  • リカルド です。

    ノマイさん、回答有難う御座います。

    >acosf()などのfloat型系の数学関数とacosl()などのlong double型系の数学関数はC99で追加された仕様であり、C90には無かった仕様でした。


    倍精度が先で、単精度が後から後からと言うのがおかしいですね。次のように想像してみました。

    ・コンピュータのハードが貧弱な黎明期に単精度が出来た。
    ・C言語が出来る頃にはハードが発展し、C言語では倍精度を標準とした。
    ・速度優先の為にC99で単精度を入れた。

  • リカルドさん、こんにちは。NoMaYです。

    確かに、単精度浮動小数点数が先なのですけれども、たぶんリカルドさんが思っているよりも、遥かに大昔ではないかと。

    IBM 704 - ウィキペディア
    ja.wikipedia.org/wiki/IBM_704

    IBM 704は、IBMが1954年4月に発表した、浮動小数点数演算ハードウェアを搭載した初の量産型コンピュータである。


    701と同様に、704は真空管論理回路と36ビットのバイナリワードを使用した。


    IBM 7090 - ウィキペディア
    ja.wikipedia.org/wiki/IBM_7090

    709は704を強化したマシンだったが、709がリリースされたころには真空管からトランジスタへと時代が移りつつあった。そこでIBMは709開発チームにトランジスタ版の後継機開発を指示した。このプロジェクトは709-T(Tは Transistorized の意)と呼ばれたが、それを「セブン・オー・ナインティ」と発音したことから、機種名が7090となった。


    IBM 7094 (1962年9月)

    倍精度浮動小数点数と関連する命令が追加されているが、7090とは大部分で互換性が保たれている。


    [追記]

    PDP-11 - ウィキペディア
    ja.wikipedia.org/wiki/PDP-11

    PDP-11ファミリは1970年1月に発表され、同年前半に出荷が開始された。


    それでも、C言語はPDP-11で実装する際にPDP-11の持つ細かい利点を活用しており、そのために後のプロセッサの設計に影響を与えた可能性はある。


  • こんにちは、

    C言語云々というと、K&Rまで遡らないと。で最初のC言語仕様でライブラリ関数は付録扱い。

    関数の引数は、int か double が標準でした。

    また、20世紀の頃、組込みはほぼ、アセンブラだったという事も意味があるかもしれません。