読者です 読者をやめる 読者になる 読者になる
管理部門で奮闘中の元ソフトウェアエンジニアによる日々雑感

マイナス金利!?

なんか全然書いてないな、このブログ...約1年ぶり。

ちょっと遅れましたが、
1/29、日本銀行(以下、日銀)はマイナス金利の導入を決定し発表しました。

マイナス金利とは?預金が減るの??

そうではないです。

日銀と民間銀行の間の話で、預金者の金利がマイナスになることではありません。
これまでは、民間銀行が日銀にお金を預けると利息が付いていたものが、
これからは、逆に日銀にお金を払わなければならなくなります。

日銀は、民間銀行がもっと貸出など市場に回して景気刺激につなげようとするのが狙いです。
が、目論んだ効果があるのかどうか・・・

短期的には株価が上昇しそうですが、
世界的に景気低迷してるので長くは続かないような気がします。

最近のヨドバシ.comが充実し過ぎ

最近のヨドバシ.comの充実ぶりは凄い。
ゴミ袋・マスク・鉛筆など日用品までかなりそろっており、
しかも送料無料で発送も非常に早い(朝6時に発送完了連絡が来たりする)。
店舗と比べて同等額か安いものなら全てヨドバシ.comで買おうかという気持ちになってしまう。

消しゴム一個でも送料無料でゆうぱっくで送ってくるのはどうかと思うし、
いずれAmazonと同じ道を辿る事になりそうだが、
対抗する通販「ヨドバシ.com」をブランドとして頑張ってほしい。

【Ubuntu Server】日本語文字化け対応

とある作業でUbuntu Serverを久々に使った。
日本語が文字化けするので設定の備忘録。

日本語ロケールがサポートされてるかを確認。

$ grep ja /usr/share/i18n/SUPPORTED
ja_JP.EUC-JP EUC-JP
ja_JP.UTF-8 UTF-8

UTF8を追加・設定。

$ sudo locale-gen ja_JP.UTF-8
$ sudo /usr/sbin/update-locale LANG=ja_JP.UTF-8

確認。

$ echo $LANG
ja_JP.UTF-8
$ echo あああ
あああ

法人税減税で賃金は上がるか?

上がらないでしょう。
人件費は営業利益を出す時点で引いています。

営業利益から経常利益を出し、
経常利益から税引前利益を出し、
税引前利益から税金を引いた額が当期利益(純利益)。
(簿記を知らない方もこの機会に損益計算書の見方を覚えましょう)

法人税減税で増えるのは当期利益(純利益)であって、
当期利益は内部留保・株主への配当原資・役員報酬に影響します。
従業員の賃金には何も関係ありません。

むしろ法人税増税のほうが賃上げするかと。
「どうせ税金で国に取られるのなら」と、従業員にボーナス出したり経費を使ったりでお金が世の中に回り、景気も良くなるんじゃないかな。

ZenFone 5


Phone - ZenFone 5 (A500KL) - ASUS

正直、この端末とMVNOで十分。
今のiPhone5sの2年縛り終わったらSIMフリースマホ+MVNOに変更します。

フィットHV5回目リコールについて思う事


短期間で多すぎるリコール。見切り発車しちゃったんだろうな・・・。
しかし「役員報酬の返上」という対応ではなく、お客様への補償へ誠意を出すべきと思いますが。
これでは株主にしか顔が向いてないですよ。

DelphiのTBitmap用 画像縮小コード

前に作ってたソフトで使っていたソースを公開。
DHGL(Delphi High-Level Graphic Library)のソースを元に加工しています。
Delphiだけでは最適化が難しいので、一部C++でSSE命令で記述しDLL化したものをcall。
SSE使用法の参考にもなるかと。

Delphi

unit BitmapUtils;

interface

uses Windows, Classes, Graphics, SysUtils;


function Shrink_SSE(Bitmap: TBitmap; Width, Height: Integer): TBitmap;

type
    TTriple = packed record
        B, G, R: Byte;
    end;
    TTripleArray = array[0..40000000] of TTriple;
    PTripleArray = ^TTripleArray;

procedure Shrink_2(S, N:pointer; SW, SH, DW, DH:integer); stdcall; external 'exf.dll';

implementation

function Shrink_SSE(Bitmap: TBitmap; Width, Height: Integer): TBitmap;
type
    TDoubleTriple = record
        B, G, R: double;
    end;
var
    NewBitmap, SourceBitmap: TBitmap;

    // 変換元のビットマップの大きさ
    SourceWidth, SourceHeight: Integer;

    // スキャンラインポインタのキャッシュ
    SourceScans, NewScans: array of PTripleArray;
    
    i: Integer;

    ScanLinePtr0  : Pointer;
    ScanLineOffset: Longint;
begin
    SourceWidth := Bitmap.Width; SourceHeight := Bitmap.Height;
    
    NewBitmap := TBitmap.Create;
    try
        // 変換先 ビットマップを作る
        NewBitmap.PixelFormat := pf24bit;
        NewBitmap.Width := Width; NewBitmap.Height := Height;
        
        // 変換元をフルカラーにする
        SourceBitmap := TBitmap.Create;
        try
            SourceBitmap.Assign(Bitmap);
            SourceBitmap.PixelFormat := pf24Bit;
            
            // スキャンラインポインタのキャッシュを作る
            SetLength(SourceScans, SourceHeight);
            SetLength(NewScans, Height);
            
            ScanLinePtr0:=SourceBitmap.ScanLine[0];
            if(SourceBitmap.Height > 0) then
                ScanLineOffset := Integer(SourceBitmap.ScanLine[1])-Integer(SourceBitmap.ScanLine[0]);
            
            for i := 0 to SourceHeight-1 do
                SourceScans[i] := Pointer(Integer(ScanLinePtr0)+ScanLineOffset*i);
            
            ScanLinePtr0:=NewBitmap.ScanLine[0];
            if(NewBitmap.Height > 0) then
                ScanLineOffset := Integer(NewBitmap.ScanLine[1])-Integer(NewBitmap.ScanLine[0]);
            
            for i := 0 to Height-1 do
                NewScans[i] := Pointer(Integer(ScanLinePtr0)+ScanLineOffset*i);
            
            Shrink_2(SourceScans, NewScans, SourceWidth, SourceHeight, Width, Height);
        finally
            SourceBitmap.Free;
        end;
    except
        NewBitmap.Free;
        Raise;
    end;
    
    Result := NewBitmap;
end;

end.

C++

#include <xmmintrin.h>

#pragma pack(1)
typedef struct {
    unsigned char B;
    unsigned char G;
    unsigned char R;
} TTriple;
#pragma pack()

typedef __declspec(align(16)) struct {
    float R;
    float G;
    float B;
    float Dummy;
} TFloatTriple;

inline int      trunc_double_sse2(double x)
{
    __asm {
        cvttsd2si eax, x
    }
}

inline int      trunc_float_sse(float x)
{
    __asm {
        cvttss2si eax, x
    }
}

extern "C" void __stdcall Shrink_2(TTriple **sourceScans, TTriple **newScans, int sourceWidth, int sourceHeight, int width, int height);

void __stdcall Shrink_2(TTriple **sourceScans, TTriple **newScans, int sourceWidth, int sourceHeight, int width, int height)
{
    int x, y, i, j;
    TTriple *pSourceScan;
    TTriple *pNewScan;
    double rectTop, rectLeft, rectRight, rectBottom;
    int trunced_rectTop, trunced_rectBottom;
    int rectLeft_i, rectRight_i;
    float ratio;
    double xRatio, yRatio;
    TFloatTriple pixel;
    TTriple sourcePixel;
    float w, h;
    
    __m128 xmmv_ratio_rcp;
    __m128 xmmv_w;
    __m128 xmmv_spx;
    __m128 xmmv_dpx;
    
    
    ratio = (double)(sourceWidth * sourceHeight) / (double)width / (double)height;
    xRatio = (double)sourceWidth / (double)width;
    yRatio = (double)sourceHeight / (double)height;
    
    xmmv_ratio_rcp = _mm_set_ps1(1 / ratio);
    
    for(y=0; y<height; y++) {
        pNewScan = newScans[y];
        
        rectTop    = y * yRatio;
        rectBottom = (y+1) * yRatio - 0.000001;
        
        trunced_rectTop = trunc_double_sse2(rectTop);
        trunced_rectBottom = trunc_double_sse2(rectBottom);
        
        for(x=0; x<width; x++) {
            // 変換先ピクセルを変換元に投影する。
            rectLeft   = x * xRatio;
            rectRight  = (x+1) * xRatio - 0.000001;
            
            rectLeft_i = trunc_double_sse2(rectLeft);
            rectRight_i = trunc_double_sse2(rectRight);

            // 変換元に投影された変換先ピクセルと交わっている
            // 変換元ピクセルを選び出し積分する
            //pixel.R = 0; pixel.G = 0; pixel.B = 0;
            xmmv_dpx = _mm_setzero_ps();

            for(j=trunced_rectTop; j<=trunced_rectBottom; j++) {
                pSourceScan = sourceScans[j];
                
                _mm_prefetch((char *)pSourceScan, _MM_HINT_NTA);
                
                for(i=rectLeft_i; i<=rectRight_i; i++) {
                    sourcePixel = pSourceScan[i];
                    
                    //_mm_prefetch((char *)&sourcePixel, _MM_HINT_NTA);

                    // 投影されたピクセルと変換元ピクセルの交わっている
                    // 部分の大きさを求める
                    if( (rectLeft < i) && ((i+1) < rectRight) )
                        w = 1;
                    else if( (i <= rectLeft) && ((i+1) < rectRight) )
                        w = 1 - (rectLeft - i);
                    else if( (rectLeft < i) && (rectRight <= (i+1)) )
                        w = rectRight - i;
                    else
                        w = rectRight - rectLeft;

                    if( (rectTop < j) && ((j+1) < rectBottom) )
                        h = 1;
                    else if( (j <= rectTop) && ((j+1) < rectBottom) )
                        h = 1 - (rectTop - j);
                    else if( (rectTop < j) && (rectBottom < (j+1)) )
                        h = rectBottom - j;
                    else
                        h = rectBottom - rectTop;
                    
                    xmmv_w = _mm_set_ps1(w * h);
                    xmmv_spx = _mm_setr_ps(sourcePixel.R, sourcePixel.G, sourcePixel.B, 0);
                    
                    xmmv_w = _mm_mul_ps(xmmv_w, xmmv_spx);
                    xmmv_dpx = _mm_add_ps(xmmv_dpx, xmmv_w);
                    
                    // 変換元 1 ピクセル分 積分
                    /*
                    pixel.R = pixel.R + w * h * sourcePixel.R;
                    pixel.G = pixel.G + w * h * sourcePixel.G;
                    pixel.B = pixel.B + w * h * sourcePixel.B;
                    */
                }
            }
            
            xmmv_dpx = _mm_mul_ps(xmmv_dpx, xmmv_ratio_rcp);
            _mm_store_ps((float *)&pixel, xmmv_dpx);
            
            
            // 積分値から平均値を求め変換先に代入する
            /*
            pNewScan[x].R = round(pixel.R / ratio);
            pNewScan[x].G = round(pixel.G / ratio);
            pNewScan[x].B = round(pixel.B / ratio);
            */
            
            pNewScan[x].R = trunc_float_sse(pixel.R);
            pNewScan[x].G = trunc_float_sse(pixel.G);
            pNewScan[x].B = trunc_float_sse(pixel.B);
        }
    }
}